K.atzlein Cocktail
不难发现最少的交换次数就是人数 减去排列形成的环的数量。
先解决 个数完全随机的情况。考虑到排列环中每个点只和两个点相连的特性,我们可以把问题等价于
条相同的绳每次选择两头相连,不生成环的次数的期望。对于一条绳而言,当且仅当他不与自己两头相连时不生成环,而每次合并后可选的绳子必然会减少一条,因此有:
。
再来考虑部分数被钦定的情况:如果合并后不形成新环,那么答案增加;而无论是否形成新环,可选的绳子都会减少一条。因此钦定 个数且形成
条新链后的答案为
。
是否形成新环可用并查集解决。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define M 998244353
int i,j,k,n,m,t,fa[500500],res;
ll inv[500500],f[500500];
int find(int x){
if(fa[x]==x){return x;}
return fa[x]=find(fa[x]);
}
int main(){
inv[1]=1;for(int i=2;i<=500000;i++){inv[i]=(M-M/i)*inv[M%i]%M;}
for(i=1;i<=500000;i++){
f[i]=(f[i-1]+inv[i]*(i-1))%M;
fa[i]=i;
}
scanf("%d",&n);
printf("%lld\n",f[n]);
for(i=1;i<=n;i++){
scanf("%d",&k);
if(find(i)!=find(k)){res++;}
fa[fa[k]]=fa[i];
printf("%lld\n",(f[n-i]+res+M)%M);
}
}
京公网安备 11010502036488号