这道题目是等价类计数裸题吧……>_>
题解:http://m.blog.csdn.net/blog/njlcazl_11109/8316340
啊其实重点还是:找出每个置换下的不动点数目
这道题比较特殊,牌的数量是限定的,所以只能DP来搞……(dp[R][G][B]表示的是R张红牌,G张绿牌,B张蓝牌在当前这个置换下,有多少种方案是会置换回自身的)
恒等置换单独处理一下即可(其实就是总染色数,多重集排列数吧……$\frac{N!}{R!G!B!}$)
最后除以m+1即可
P.S.因为是模意义下,所以所有的除法都是乘逆元。。。
1 /************************************************************** 2 Problem: 1004 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:104 ms 7 Memory:1708 kb 8 ****************************************************************/ 9 10 //BZOJ 1004 11 #include<cstdio> 12 #include<cstring> 13 #include<cstdlib> 14 #include<iostream> 15 #include<algorithm> 16 #define rep(i,n) for(int i=0;i<n;++i) 17 #define F(i,j,n) for(int i=j;i<=n;++i) 18 #define D(i,j,n) for(int i=j;i>=n;--i) 19 #define pb push_back 20 using namespace std; 21 typedef long long LL; 22 inline int getint(){ 23 int r=1,v=0; char ch=getchar(); 24 for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; 25 for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; 26 return r*v; 27 } 28 const int N=110; 29 /*******************template********************/ 30 int n,m,p,R,G,B; 31 int f[N][N],c[N]; 32 int dp[N][30][30]; 33 34 int Pow(int a,int b,int P){ 35 int r=1; 36 for(;b;b>>=1,a=a*a%P) 37 if (b&1) r=r*a%P; 38 return r; 39 } 40 bool vis[N]; 41 int main(){ 42 #ifndef ONLINE_JUDGE 43 freopen("1004.in","r",stdin); 44 freopen("1004.out","w",stdout); 45 #endif 46 R=getint(); B=getint(); G=getint(); m=getint(); p=getint(); 47 n=R+G+B; 48 int sum=1,cnt=0,num; 49 F(i,1,n) sum=(sum*i)%p; 50 F(i,1,R) sum=(sum*Pow(i,p-2,p))%p; 51 F(i,1,G) sum=(sum*Pow(i,p-2,p))%p; 52 F(i,1,B) sum=(sum*Pow(i,p-2,p))%p; 53 F(i,1,m) F(j,1,n) f[i][j]=getint(); 54 F(i,1,m){ 55 memset(vis,0,sizeof vis); 56 memset(dp,0,sizeof dp); 57 memset(c,0,sizeof c); 58 cnt=0; 59 F(j,1,n) if (!vis[j]){ 60 int tmp=j,num=0; 61 while(!vis[tmp]){ 62 vis[tmp]=1; 63 tmp=f[i][tmp]; 64 num++; 65 } 66 c[++cnt]=num; 67 } 68 // printf("cnt=%d\n",cnt); 69 // F(i,1,cnt) printf("%d ",c[i]); puts(""); 70 dp[0][0][0]=1; 71 F(j,1,cnt) F(r,1,R) F(g,1,G) F(b,1,B){ 72 if (r>=c[j]) (dp[r][g][b]+=dp[r-c[j]][g][b])%=p; 73 if (g>=c[j]) (dp[r][g][b]+=dp[r][g-c[j]][b])%=p; 74 if (b>=c[j]) (dp[r][g][b]+=dp[r][g][b-c[j]])%=p; 75 // printf("dp[%d][%d][%d]=%d\n",r,g,b,dp[r][g][b]); 76 } 77 sum=(sum+dp[R][G][B])%p; 78 } 79 sum=(sum*Pow(m+1,p-2,p))%p; 80 printf("%d\n",sum); 81 return 0; 82 }