置换群+dp
1 #include<cstdio> 2 #include<cstdlib> 3 #include<algorithm> 4 #include<cstring> 5 #include<vector> 6 #include<cmath> 7 #define MAXN 65 8 #define ll long long 9 #define pb push_back 10 #define ft first 11 #define sc second 12 #define mp make_pair 13 using namespace std; 14 int Inv(int a,int p){ 15 int b=p-2; 16 int ret=1; 17 while(b){ 18 if(b&1){ 19 ret=1LL*ret*a%p; 20 } 21 a=1LL*a*a%p; 22 b>>=1; 23 } 24 return ret; 25 } 26 int sr,sb,sg,n,m,MOD; 27 int a[MAXN][MAXN]; 28 int f[25][25][25]; 29 int b[MAXN],d[MAXN]; 30 int calc(int x){ 31 memset(b,0,sizeof(b)); 32 memset(d,0,sizeof(d)); 33 int cnt=0; 34 for(int i=1;i<=n;i++){ 35 if(!b[i]){ 36 cnt++; 37 for(int j=i;!b[j];j=a[x][j]){ 38 d[cnt]++; 39 b[j]=1; 40 } 41 } 42 } 43 memset(f,0,sizeof(f)); 44 f[0][0][0]=1; 45 for(int h=1;h<=cnt;h++){ 46 for(int i=sr;i>=0;i--){ 47 for(int j=sb;j>=0;j--){ 48 for(int k=sg;k>=0;k--){ 49 if(i>=d[h])(f[i][j][k]+=f[i-d[h]][j][k])%=MOD; 50 if(j>=d[h])(f[i][j][k]+=f[i][j-d[h]][k])%=MOD; 51 if(k>=d[h])(f[i][j][k]+=f[i][j][k-d[h]])%=MOD; 52 } 53 } 54 } 55 } 56 return f[sr][sb][sg]; 57 } 58 int main() 59 { 60 // freopen("data.in","r",stdin); 61 scanf("%d%d%d%d%d",&sr,&sb,&sg,&m,&MOD); 62 n=sr+sb+sg; 63 int t; 64 for(int i=1;i<=m;i++){ 65 for(int j=1;j<=n;j++){ 66 scanf("%d",&t); 67 a[i][t]=j; 68 } 69 } 70 m++; 71 for(int i=1;i<=n;i++)a[m][i]=i; 72 int ans=0; 73 for(int i=1;i<=m;i++){ 74 ans+=calc(i); 75 ans%=MOD; 76 } 77 ans=1LL*ans*Inv(m,MOD)%MOD; 78 printf("%d\n",ans); 79 return 0; 80 }