解题:HNOI 2013 Cards

题面

除了不洗牌以外,每种洗牌方式的每个循环里的颜色必须一样,然后大力背包一下就好了。最后记得把不洗牌的方案也算进去

 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 }
View Code
原文地址:https://www.cnblogs.com/ydnhaha/p/10307088.html