除了不洗牌以外,每种洗牌方式的每个循环里的颜色必须一样,然后大力背包一下就好了。最后记得把不洗牌的方案也算进去
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=64; 6 int n,m,p,c1,c2,c3,ans; 7 int dp[2][N][N][N],noww,last; 8 int trs[N][N],vec[N][N],siz[N],vis[N]; 9 void exGCD(int a,int b,int &x,int &y) 10 { 11 if(!b) x=1,y=0; 12 else exGCD(b,a%b,y,x),y-=a/b*x; 13 } 14 int Inv(int x) 15 { 16 int xx,yy; 17 exGCD(x,p,xx,yy); 18 return (xx%p+p)%p; 19 } 20 void Mod(int &x,int y) 21 { 22 x+=y; 23 if(x>=p) x-=p; 24 } 25 void Getcir(int idx,int pos) 26 { 27 vis[pos]=true,vec[idx][siz[idx]]++; 28 if(!vis[trs[idx][pos]]) 29 Getcir(idx,trs[idx][pos]); 30 } 31 int main() 32 { 33 scanf("%d%d%d%d%d",&c1,&c2,&c3,&m,&p),n=c1+c2+c3; 34 for(int i=1;i<=m;i++) 35 { 36 for(int j=1;j<=n;j++) 37 scanf("%d",&trs[i][j]); 38 memset(vis,0,sizeof vis); 39 for(int j=1;j<=n;j++) 40 if(!vis[j]) siz[i]++,Getcir(i,j); 41 } 42 for(int i=1;i<=m;i++) 43 { 44 memset(dp,0,sizeof dp),noww=dp[0][0][0][0]=1,last=0; 45 for(int j=1;j<=siz[i];j++) 46 { 47 int sz=vec[i][j]; 48 for(int k=0;k<=c1-sz;k++) 49 for(int h=0;h<=c2-sz;h++) 50 for(int l=0;l<=c3-sz;l++) 51 { 52 int t=dp[last][k][h][l]; 53 if(k+sz<=c1) Mod(dp[noww][k+sz][h][l],t); 54 if(h+sz<=c2) Mod(dp[noww][k][h+sz][l],t); 55 if(l+sz<=c3) Mod(dp[noww][k][h][l+sz],t); 56 } 57 last=noww,noww^=1; 58 } 59 ans+=dp[last][c1][c2][c3],ans%=p; 60 } 61 memset(dp,0,sizeof dp),noww=dp[0][0][0][0]=1,last=0; 62 for(int i=1;i<=n;i++) 63 { 64 for(int k=0;k<=c1;k++) 65 for(int h=0;h<=c2;h++) 66 for(int l=0;l<=c3;l++) 67 { 68 int t=dp[last][k][h][l]; 69 if(k+1<=c1) Mod(dp[noww][k+1][h][l],t); 70 if(h+1<=c2) Mod(dp[noww][k][h+1][l],t); 71 if(l+1<=c3) Mod(dp[noww][k][h][l+1],t); 72 } 73 last=noww,noww^=1; 74 } 75 printf("%lld",1ll*(ans+dp[last][c1][c2][c3])*Inv(m+1)%p); 76 return 0; 77 }