题目
做法
一种置换各个循环里的颜色相同,这个手玩就懂了(唯一性)
三维背包就能做,最后再加个不变的一种置换
My complete code
#include<bits/stdc++.h>
using namespace std;
typedef int LL;
LL const maxn=30;
LL r,b,g,m,p,n,ans;
LL dp[maxn][maxn][maxn],len[maxn*3],a[maxn*3];
bool visit[maxn*3];
inline LL Pow(LL base,LL b){
LL ret(1);
while(b){
if(b&1) ret=ret*base%p;
base=base*base%p,b>>=1;
}return ret;
}
inline LL Dp(){
LL cnt(0);
memset(visit,false,sizeof(visit));
memset(len,0,sizeof(len));
memset(dp,0,sizeof(dp));
for(LL i=1;i<=n;++i){
if(!visit[i]){
++cnt;
for(LL j=i;!visit[j];j=a[j])
visit[j]=true,++len[cnt];
}
}
dp[0][0][0]=1;
for(LL i=1;i<=cnt;++i)
for(LL R=r;R>=0;--R)
for(LL B=b;B>=0;--B)
for(LL G=g;G>=0;--G){
if(R>=len[i]) dp[R][B][G]=(dp[R][B][G]+dp[R-len[i]][B][G])%p;
if(B>=len[i]) dp[R][B][G]=(dp[R][B][G]+dp[R][B-len[i]][G])%p;
if(G>=len[i]) dp[R][B][G]=(dp[R][B][G]+dp[R][B][G-len[i]])%p;
}
return dp[r][b][g];
}
int main(){
scanf("%d%d%d%d%d",&r,&b,&g,&m,&p);
n=r+b+g;
for(LL i=1;i<=m;++i){
for(LL j=1;j<=n;++j) scanf("%d",a+j);
ans=(ans+Dp())%p;
}
for(LL i=1;i<=n;++i) a[i]=i;
ans=(ans+Dp())%p;
printf("%d",ans*Pow(m+1,p-2)%p);
return 0;
}