[BZOJ1004]Cards
polya定理+乘法逆元
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define maxn 65 4 #define maxs 25 5 int sr,sb,sg,n,m,p; 6 int a[maxn][maxn],f[maxs][maxs][maxs],vis[maxn],cal[maxn]; 7 8 int dp(int x){ 9 memset(vis,0,sizeof(vis)); 10 memset(f,0,sizeof(f)); 11 int cc=0; 12 for(int i=1;i<=n;i++){ 13 if(!vis[i]){ 14 vis[i]=1; 15 cal[++cc]=1; 16 int ii=i; 17 while(!vis[a[x][ii]]){ 18 vis[a[x][ii]]=1; 19 cal[cc]++; 20 ii=a[x][ii]; 21 } 22 } 23 } 24 f[0][0][0]=1; 25 for(int t=1;t<=cc;t++) 26 for(int i=sr;i>=0;i--) 27 for(int j=sb;j>=0;j--) 28 for(int k=sg;k>=0;k--){ 29 if(i>=cal[t])f[i][j][k]=(f[i][j][k]+f[i-cal[t]][j][k])%p; 30 if(j>=cal[t])f[i][j][k]=(f[i][j][k]+f[i][j-cal[t]][k])%p; 31 if(k>=cal[t])f[i][j][k]=(f[i][j][k]+f[i][j][k-cal[t]])%p; 32 } 33 return f[sr][sb][sg]; 34 } 35 int main(){ 36 scanf("%d%d%d%d%d",&sr,&sb,&sg,&m,&p); 37 n=sr+sb+sg; 38 for(int i=1;i<=m;i++) 39 for(int j=1;j<=n;j++) 40 scanf("%d",&a[i][j]); 41 m++; 42 for(int i=1;i<=n;i++)a[m][i]=i; 43 int ans=0; 44 for(int i=1;i<=m;i++) 45 ans=(ans+dp(i))%p; 46 for(int i=1;i<=p-2;i++) 47 ans=(ans*m)%p; 48 printf("%d\n",ans); 49 return 0; 50 }