HNOI 2008--Cards( 置換群 & DP )
阿新 • • 發佈:2017-09-18
while clu http solution h+ pri scan -- printf
對群論沒有任何了解的自覺百度。。。
題目鏈接:
http://www.lydsy.com/JudgeOnline/problem.php?id=1003
Solution
請百度“ 伯恩賽德引理 ”。。。
這是一道置換群的題目。。。雖然還要加上DP。。。
如果明白伯恩賽德引理的話。。直接套公式即可。。。
代碼
#include<cstdio> #include<iostream> #include<cstring> #define LL long long using namespace std; int sr,sb,sg,m,n,mod,ans; int f[70][70][70],g[70],d[70]; bool c[70]; int DP(){ for(int i=1;i<=n;i++) c[i]=0; int sum=0,q; for(int i=1;i<=n;i++) if(!c[i]){ d[++sum]=0;q=i; while(!c[g[q]]){ d[sum]++; q=g[q]; c[q]=1; } } for(int i=0;i<=sr;i++) for(int j=0;j<=sb;j++) for(int k=0;k<=sg;k++) f[i][j][k]=0; f[0][0][0]=1; for(int h=1;h<=sum;h++) for(int i=sr;i>=0;i--) for(int j=sb;j>=0;j--) for(int k=sg;k>=0;k--){ if(i>=d[h]) f[i][j][k]=(f[i][j][k]+f[i-d[h]][j][k])%mod; if(j>=d[h]) f[i][j][k]=(f[i][j][k]+f[i][j-d[h]][k])%mod; if(k>=d[h]) f[i][j][k]=(f[i][j][k]+f[i][j][k-d[h]])%mod; } return f[sr][sb][sg]; } int pow(int a,int b){ int s=1; while(b){ if(b&1) s=s*a%mod; b>>=1; a=a*a%mod; } return s; } int main(){ ans=0; scanf("%d%d%d%d%d",&sr,&sb,&sg,&m,&mod); f[0][0][0]=1; n=sr+sb+sg; for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++) scanf("%d",&g[j]); ans=(ans+DP())%mod; } for(int i=1;i<=n;i++) g[i]=i; ans=(ans+DP())%mod; m++; ans=ans*pow(m,mod-2)%mod; printf("%d\n",ans); return 0; }
This passage is made by Yukino.
HNOI 2008--Cards( 置換群 & DP )