zoukankan      html  css  js  c++  java
  • 【CF 715E】Complete the Permutations

    题目

    自闭了一晚上,终于看懂题解在说啥了;

    首先考虑对于两个给定的排列最小交换次数是多少,不难发现就是(n- ext{置换数}),置换数就是令(a_i->b_i)后图中的环的个数,每一个置换也就是环可以少交换一次;

    对于这道题,还是令(a_i)(b_i)连边,我们用(0)来表示未知数,这样整个图中大概就有怎么情况

    • 已知边形成的环

    • (0->x_1->x_2->x_3->dots x_n)

    • (x_1->x_2->x_3->dots x_n->0)

    • (0->x_1->x_2->x_3->dots x_n->0)

    首先已经形成的环就没啥影响了,对于后三种情况,我们把(x_i->x_{i+1})这类边缩掉,于是整个图中就只剩下(x->0,0->x,0->0)这三种边,考虑这些边的成环情况;

    不难发现(x->0,0->y)是不能成环的,因为(x)没有入度说明在(B)中没有出现,(y)没有入度说明在(B)中出现;而(x->0)成环本质上就是使得(0)成为(x)

    考虑(x->0)边的成环情况,设(g_i)表示至少形成了(i)个环,设有(k)(x->0)边,(h)(0->0)边,于是有

    [g_i=sum_{j=i}^{k}inom{k}{j}egin{bmatrix}j\iend{bmatrix}(h+k-j)^{underline {k-j}} ]

    枚举成环的边有(j)条,从一共(k)条边里选(j)条边出来,之后分到(i)个环中去,对于剩下的(k-j)条边每条边找一条(0->0)边或不在环中的(x->0)边连过去,所以是一个下降幂。注意连到(0->0)边是实际上没啥影响,(0->0)边仍然是(0->0)边,就是延长了一下。

    (0->x)边同理;我们求出(g)后来个二项式反演,就是求出恰好的情况了。我们把这两种边求出的结果卷积一波,就是(x)环的情况了;对于(0->0)边也能成环,成环情况就是第一类斯特林数,于是再和第一类斯特林数卷积一下;同时由于(0->0)边的的顺序可以自由钦定,所以还需要乘上(h!)

    代码

    #include<bits/stdc++.h>
    #define re register
    #define LL long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    inline int read() {
    	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    const int mod=998244353;const int maxn=255;
    inline int dqm(int x) {return x<0?x+mod:x;}
    inline int qm(int x) {return x>=mod?x-mod:x;}
    inline int ksm(int a,int b) {
    	int S=1;for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)S=1ll*S*a%mod;return S;
    }
    struct E{int v,nxt;}e[maxn];
    int cnt[2],h,num,tot,n,vis[maxn],vit[maxn],in[maxn],out[maxn];
    int fac[maxn],a[maxn],ifac[maxn],b[maxn],S[maxn][maxn],head[maxn],g[4][maxn];
    inline int C(int n,int m) {
    	return m>n?0:1ll*fac[n]*ifac[m]%mod*ifac[n-m]%mod;
    }
    inline int A(int n,int m) {
    	return m>n?0:1ll*fac[n]*ifac[n-m]%mod;
    }
    inline void add(int x,int y){
    	e[++num].v=y;e[num].nxt=head[x];head[x]=num;
    }
    void dfs1(int x) {
    	if(x==0&&vis[x]) {++h;return;}
    	if(!head[x]&&x) {++cnt[1];return;}
    	if(vis[x])return;vis[x]=1;
    	for(re int i=head[x];i;i=e[i].nxt)dfs1(e[i].v);
    }
    void dfs2(int x) {
    	if(!head[x]&&x) {++cnt[0];return;}
    	if(vit[x])return;vit[x]=1;
    	for(re int i=head[x];i;i=e[i].nxt)dfs2(e[i].v);
    }
    int dfs3(int x,int st) {
    	if(x==st&&vis[st]) return 1;
    	if(vis[x]) return 0;vis[x]=1;
    	for(re int i=head[x];i;i=e[i].nxt)return dfs3(e[i].v,st);
    	return 0;
    }
    inline void solve(int *f,int k) {
    	for(re int i=0;i<=k;i++)
    		for(re int j=i;j<=k;j++) 
    			f[i]=qm(f[i]+1ll*C(k,j)*S[j][i]%mod*A(h+k-j,k-j)%mod);
    	for(re int nw=0,i=0;i<=k;f[i]=nw,nw=0,++i) 
    		for(re int j=i;j<=n;j++) {
    			if((j-i)&1) nw=dqm(nw-1ll*C(j,i)*f[j]%mod);
    			else nw=qm(nw+1ll*C(j,i)*f[j]%mod);
    		}
    }
    int main() {
    	n=read();
    	for(re int i=1;i<=n;i++)a[i]=read();
    	for(re int i=1;i<=n;i++)b[i]=read();
    	fac[0]=ifac[0]=1;
    	for(re int i=1;i<=n;i++)fac[i]=1ll*fac[i-1]*i%mod;
    	ifac[n]=ksm(fac[n],mod-2);
    	for(re int i=n-1;i;i--)ifac[i]=1ll*ifac[i+1]*(i+1)%mod;
    	S[0][0]=1;
    	for(re int i=1;i<=n;i++)
    		for(re int j=1;j<=i;j++)
    			S[i][j]=qm(S[i-1][j-1]+1ll*(i-1)*S[i-1][j]%mod);
    	for(re int i=1;i<=n;i++)add(a[i],b[i]);dfs1(0);
    	num=0;memset(head,0,sizeof(head));
    	for(re int i=1;i<=n;i++)add(b[i],a[i]);dfs2(0);
    	for(re int i=1;i<=n;i++)in[a[i]]++,out[b[i]]++,vis[i]|=vit[i];
    	for(re int i=1;i<=n;i++)if(in[i]==out[i]&&in[i]==1&&!vis[i])tot+=dfs3(i,i);
    	solve(g[0],cnt[0]);solve(g[1],cnt[1]);
    	for(re int i=0;i<=n;i++)
    		for(re int j=i;j>=0;j--) g[2][i]=qm(g[2][i]+1ll*g[0][j]*g[1][i-j]%mod);
    	for(re int i=0;i<=n;i++) 
    		for(re int j=0;j<=i;j++) g[3][i]=qm(g[3][i]+1ll*g[2][j]*S[h][i-j]%mod);
    	for(re int i=0;i<=n;i++) g[3][i]=1ll*g[3][i]*fac[h]%mod;
    	for(re int i=0;i<n;i++) printf("%d ",n-i-tot>=0?g[3][n-i-tot]:0);
    	return 0;
    }
    
  • 相关阅读:
    csu 1141 节能
    WA:ZOJ 1025 Wooden Sticks
    UVa 531 Compromise
    UVa 437 The Tower of Babylon
    UVa 10285 Longest Run on a Snowboard
    在asp.net使用web.config身份验证
    掌握 Ajax,第 6 部分: 建立基于 DOM 的 Web 应用程序
    面向对象编程思想
    一步一步学Remoting之五:异步操作
    Asp.net 2.0 用 FileUpload 控件实现多文件上传 用户控件(示例代码下载)
  • 原文地址:https://www.cnblogs.com/asuldb/p/12313631.html
Copyright © 2011-2022 走看看