题解:AT_abc470_f [ABC470F] Googol Swaps

· · 题解

观前提醒:题解中的每个在原题面中出现过的变量含义均与原题相同。

Atcoder 题目传送门

思路

对于每个 A_iB_i 我们连一条无向边,不难发现每个连通块的答案相互独立,可以先算每个连通块内的答案数量然后用乘法原理乘起来。

题目说必须交换 10^{100} 次,非常大,可以认为交换次数无限,也就是排列数。但是!题目没有保证没有相同的字符,所以就是排列数的一种特殊类型:可重集的排列。

可重集的排列其实非常简单啦。设联通块内每个字母出现的次数为 t_i,连通块大小为 siz,排列数为 \frac{siz!}{t_1!\times t_2!\times \cdots t_{26}!},快速幂求一下逆元即可。

坑点

写到这里你会发现样例 2 过不了,然后你手摸一遍发现没问题啊,就是 36 啊,为啥样例输出是 18,然后你就会被卡半个小时。

(估计只有我这么唐)

问题出在这句话上:必须交换 10^{100} 次,非常大,可以认为交换次数无限。

然后样例 $1$ 和 $3$ 过不了了,不难发现,如果存在一个 $i$,使得 $S_{A_i}=S_{B_i}$,需要交换奇数次的排列也可以达成了。特判一下即可。 --- ::::success[AC Code] ```cpp #include<bits/stdc++.h> #define wef(i,l,r) for(int i=l;i<=r;i++) #define few(i,r,l) for(int i=r;i>=l;i--) #define re read() #define pii pair<int,int> #define endl putchar('\n') using ll=long long; using namespace std; inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();return x*f;} inline bool write(auto x,char fg=0){bool neg=0;if(x<0){neg=1;putchar('-');}static int sta[40];int top=0;do{sta[top++]=x%10;x/=10;}while(x);if(neg) while(top) putchar('0'-sta[--top]); else while(top) putchar('0'+sta[--top]);if(fg) putchar(fg);return 0;} const int N=3e5+5,mod=998244353; #define int long long string a; vector<int> g[N]; int t[N][26],v[N],cnt; void dfs(int x){ t[cnt][a[x]-'a']++; for(int y:g[x]){ if(v[y]) continue; v[y]=1; dfs(y); } } int fac[N]; inline int qpow(int a,int b){ int res=1; while(b){ if(b&1) res=res*a%mod; b>>=1,a=a*a%mod; } return res; } signed main(){ int n=re,m=re; cin>>a; a=" "+a; wef(i,1,m){ int x=re,y=re; g[x].push_back(y); g[y].push_back(x); } bool free=0,lar=0; wef(i,1,n){ if(!v[i]){ v[i]=1; cnt++; dfs(i); int sum=0; bool dup=0; wef(j,0,25){ sum+=t[cnt][j]; if(t[cnt][j]>=2) dup=1; } if(sum>=2){ lar=1; if(dup) free=1; } } } fac[0]=1; wef(i,1,n) fac[i]=fac[i-1]*i%mod; int res=1; if(!free&&lar) res=qpow(2,mod-2); wef(i,1,cnt){ int sum=0, mul=1; wef(j,0,25){ mul=fac[t[i][j]]*mul%mod; sum+=t[i][j]; } res=res*fac[sum]%mod*qpow(mul,mod-2)%mod; } write(res); return 0; } ``` ::::