首页 > 其他分享 >猜排列 题解

猜排列 题解

时间:2024-06-08 15:33:38浏览次数:20  
标签:排列 int 题解 子图 su hd

猜排列 题解

差 eps 步想到正解。

题意描述

有 \(m\) 个长为 \(n\) 序列 \(a_1,\dots,a_n\),还有 \(m\) 个长为 \(n\) 序列 \(b_1,\dots,b_n\)。

其中 \(b_i\) 是由 \(a_i\) 通过排列 \(p\) 置换得到的,\(b_{p_i}=a_i\)。

现在又要求出排列 \(p\) 会有多种可能,模 \(998244353\)。

Solution

首先手玩样例,发现如果这 \(m\) 次 \(a\) 的某个位置和 \(b\) 的某个位置都是相等的,可以确保一定有一种可能的 \(p\) 排列使他们就是通过置换得到的。

有点像二分图,连个边再说。

发现有些位置是可以同时连不同的位置的(那当然了,不然答案就是唯一的,输出 \(1\) 就好了),这时发现,对面也可以向我们连边。而无论哪个样例,似乎连出来的二分图都是一个部的每个点都连向了另一个部的每个点。

那这个子图贡献的就是子图所有点 \(\div 2\) 的数量的阶乘。(就全排列嘛,除以二是因为二分图上下两部的点的数量是对称的)

考场就想到这里,发现如果要找子图的话是 \(O(n^2m)\) 的。含泪 80pts。

差那一步呢?

我们发现,同一位上的 \(m\) 次可以压成哈希。这样的话如果本来就是同一子图,那哈希值相等。

也不用建图了,因为可用 map 统计点数,不需要把图真正建出来去跑。

#include <bits/stdc++.h>
using namespace std;

#define int long long

const int N = 6e5 + 5, P = 998244353, base = 19491001, P0 = 20090327, P1 = 20070923;

int T, n, m;
int fac[N], inv[N], cnt[N];
bool vis[N];
unsigned int a[N][2], b[N][2];
int su, en[N], lt[N], hd[N];
map<pair<unsigned int, unsigned int>, unsigned int> mp1, mp2;
map<pair<unsigned int, unsigned int>, bool> Vis;

void add(int u, int v) { en[++su] = v, lt[su] = hd[u], hd[u] = su; }

void init() {
    fac[0] = 1;
    for (int i = 1; i <= N - 5; i++) fac[i] = fac[i - 1] * i % P;
}

inline void solve() {
    memset(a, 0, sizeof a);
    memset(b, 0, sizeof b);
    scanf("%lld%lld", &n, &m);
    for (int i = 1; i <= m; i++) {
        int x;
        for (int j = 1; j <= n; j++) {
            scanf("%lld", &x);
            a[j][0] = (1ll * a[j][0] * base + x) % P0;
            a[j][1] = (1ll * a[j][1] * base + x) % P1;
        }
        for (int j = 1; j <= n; j++) {
            scanf("%lld", &x);
            b[j][0] = (1ll * b[j][0] * base + x) % P0;
            b[j][1] = (1ll * b[j][1] * base + x) % P1;
        }
    }
    mp1.clear(), mp2.clear();
    Vis.clear();
    for (int i = 1; i <= n; i++) mp1[{ a[i][0], a[i][1] }]++, mp2[{ b[i][0], b[i][1] }]++;
    int ans = 1;
    for (int i = 1; i <= n; i++) {
        if (!Vis[{ a[i][0], a[i][1] }]) {
            Vis[{ a[i][0], a[i][1] }] = 1;
            if (mp1[{ a[i][0], a[i][1] }] != mp2[{ a[i][0], a[i][1] }])
                ans = 0;
            else
                ans = ans * fac[mp1[{ a[i][0], a[i][1] }]] % P;
        }
    }
    printf("%lld\n", ans);
}

signed main() {
    // freopen("interact.in","r",stdin);
    // freopen("interact.out","w",stdout);
    scanf("%lld", &T);
    init();
    while (T--) solve();
    return 0;
}

标签:排列,int,题解,子图,su,hd
From: https://www.cnblogs.com/holmes-wang/p/18238652

相关文章

  • P10466 邻值查找 题解
    题目传送门前置知识二叉搜索树&平衡树解法笔者写这篇题解的时候题面应该是出锅了,建议去看Acwing的题面。第一问同luoguP2234[HNOI2002]营业额统计,平衡树维护前驱、后继(非严格意义上的)求出差值后取\(\min\)即可;第二问用map实现一个映射即可维护位置。代码#incl......
  • P10499 开关问题 题解
    题目传送门前置知识高斯消元法解异或方程组|乘法原理解法把开关的相互影响关系转化成异或,然后就转化成了异或方程组,高斯消元求解即可。判断是否存在解的过程同luoguP2455[SDOI2006]线性方程组。由于自由元仅能取\(0/1\),故总方案数为\(2\)的自由元数量次方。代码......
  • P7219 [JOISC2020] 星座 3 题解
    会发现题目的坐标其实是平面直角坐标系。我们按\(y\)坐标从小到大考虑所有的星星,假设当前考虑到了星星\(i\)。我们先计算出之前所有能够影响到\(i\)的星星的代价和为\(cost\)(可以用树状数组维护)。然后分类讨论。若\(c_i\lecost\),那么肯定直接将\(i\)直接涂黑,因为它更......
  • ABB 圆型排列产品码垛
    MoveJP_HOME,v1000,fine,My_Tool;xd_3_3:=RelTool(p10,0,0,0\Rz:=-index*45);Resetdo_0;index:=0;WHILE(index<21)DOMoveJOffs(pick,0,0,100),v1000,fine,My_Tool\WObj:=wobjPingMing2;WaitDId......
  • P10560 [ICPC2024 Xi'an I] The Last Cumulonimbus Cloud 题解
    好好玩的题。思路对于一个图上邻域问题,我们有一个很经典的做法:根号分治。考虑根号分治的本质是什么。我们把点分成两类,平衡每一种点的时间,也就是度数大的与度数小的点。所以对于这道题,我们有了更加好的做法。发现题目给的图的性质就是一个天然的划分方案。我们每次找到图中......
  • P10553 [ICPC2024 Xi'an I] Guess The Tree 题解
    挺有意思的题。思路考虑一个比较自然的做法。我们每次对于一棵树,我们将它的某一条链抽出来。这样,我们只需要知道这颗树的所有节点与链底的\(\text{lca}\),就可以知道它是属于这条链上哪一个节点的下面。然后就可以递归处理。由于交互库不是自适应的。我们可能可以想到随机......
  • P9000 [CEOI2022] Measures 题解
    思路简单题。考虑任意两点之间的限制。任意两点合法时必须要满足:\[\frac{d(j-i)-(a_j-a_i)}{2}\let(i\lej)\]所以答案即为:\[\max_{i\lej}\frac{d(j-i)-(a_j-a_i)}{2}\]使用线段树简单维护即可。时间复杂度:\(O((n+m)\log(n+m))\)。Code#include<bits/stdc++.h>using......
  • CF1192B Dynamic Diameter 题解
    思路静态\(\text{toptree}\)板子题。定义我们使用簇来表示树上的一个连通块。可以按照如下方式定义一个簇:一个簇可以表示为三元组\((u,v,E)\),其中\(u,v\)为树的节点,称为簇的界点,\(E\)为一个边的集合,表示该簇包含的边,路径\((u,v)\)称作簇路径。\(u,v\)分别为上界......
  • 无限之环 题解
    五星压行大师\(lyh\)表示:这是难得能让他的代码长度打破百行大关的题目(182行)。首先,根据科技与狠活,本题可以黑白染色。源点联向白格,黑格连向汇点。发现每个格子都可以连向四个方向,所以可以建立四个点,代表水管连到了上下左右四个方向。设四元组\((x,y,z,p)\)表示水管初始状态......
  • 开车旅行|倍增优化dp+双端列表/set|题解
    题面:题面链接这题的思路值得借鉴,也是我做的第一道倍增优化dp题目.比较好的是题目的意思较为清晰,所以不再赘述.解析:这里我们可以非常直接的想到暴力模拟,因为第一眼看上去前七个点的数据范围是支持我们进行一个简单的预处理得到对应人在对应位置的决策的.(排序O(n×sqrt(......