bzoj1004 [HNOI2008]Cards
传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1004
【题解】
Burnside引理,考虑Polya原理的推导,由于循环节必须染相同的颜色,那么可以dp出方案。
1 # include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 110; 5 int A, B, C, m, mod, n; 6 int p[N][N]; 7 bool vis[N]; 8 int w[N], wn; 9 int f[N][N][N]; 10 11 inline int dp(int id) { 12 wn = 0; 13 for (int i=1; i<=n; ++i) vis[i] = 0; 14 for (int i=1; i<=n; ++i) { 15 if(vis[i]) continue; 16 int x = i, t = 0; 17 while(vis[x] == 0) { 18 vis[x] = 1; 19 x = p[id][x]; 20 ++ t; 21 } 22 w[++wn] = t; 23 } 24 for (int i=0; i<=A; ++i) 25 for (int j=0; j<=B; ++j) 26 for (int k=0; k<=C; ++k) f[i][j][k] = 0; 27 f[0][0][0] = 1; 28 for (int cur=1; cur<=wn; ++cur) 29 for (int i=A; i>=0; --i) 30 for (int j=B; j>=0; --j) 31 for (int k=C; k>=0; --k) { 32 if(i >= w[cur]) { 33 f[i][j][k] = f[i][j][k] + f[i-w[cur]][j][k]; 34 if(f[i][j][k] >= mod) f[i][j][k] -= mod; 35 } 36 if(j >= w[cur]) { 37 f[i][j][k] = f[i][j][k] + f[i][j-w[cur]][k]; 38 if(f[i][j][k] >= mod) f[i][j][k] -= mod; 39 } 40 if(k >= w[cur]) { 41 f[i][j][k] = f[i][j][k] + f[i][j][k-w[cur]]; 42 if(f[i][j][k] >= mod) f[i][j][k] -= mod; 43 } 44 } 45 return f[A][B][C]; 46 } 47 48 inline int pwr(int a, int b) { 49 int ret = 1; 50 while(b) { 51 if(b&1) ret = ret * a % mod; 52 a = a * a % mod; 53 b >>= 1; 54 } 55 return ret; 56 } 57 58 59 int main() { 60 cin >> A >> B >> C >> m >> mod; 61 n = A + B + C; 62 for (int i=1; i<=m; ++i) 63 for (int j=1; j<=n; ++j) cin >> p[i][j]; 64 ++m; 65 for (int i=1; i<=n; ++i) p[m][i] = i; 66 int ans = 0; 67 for (int i=1; i<=m; ++i) { 68 ans = ans + dp(i); 69 if(ans >= mod) ans -= mod; 70 } 71 ans = ans * pwr(m, mod-2) % mod; 72 cout << ans << endl; 73 return 0; 74 }