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 }
View Code

 

转载于:https://www.cnblogs.com/galaxies/p/bzoj1004.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值