zoukankan      html  css  js  c++  java
  • bzoj 1004 [HNOI2008]Cards

    初次接触置换群,学习了一下burnside引理和polya定理

    burnside 引理:  (只是结论,证明并没有搞懂)

    除了题目已给的置换,还应添加一个所有纸牌都指向它自己的置换

    本质不同的染色方案为所有置换中1阶循环(也就是不变元素, 一个染色方案经过该置换后不变)的个数

    这样的元素,每个置换中在同一循环节中的纸牌一定属于同一种颜色,所以可以直接进行背包dp

     1 #define MAXN 70UL
     2 #include <cstdio>
     3 #include <cstring>
     4 
     5 using namespace std;
     6 
     7 int n, s1, s2, s3, m, p, tot, f[25][25][25], d[MAXN], a[MAXN][MAXN];
     8 bool vis[MAXN];
     9 
    10 int Ksm(int x, int k, int mod) {
    11     int ret = 1;
    12     while(k) {
    13         if(k&1) ret = ret*x%mod;
    14         x = x*x%mod;
    15         k >>= 1;
    16     }
    17     return ret;
    18 }
    19 
    20 int Dp(int x) {
    21     memset(vis, false, sizeof(vis[0])*(n+1));
    22     memset(d, 0, sizeof(d[0])*(tot+1));
    23     tot = 0;
    24     for(int i = 1 ; i <= n ; ++ i) if(!vis[i]) {
    25         ++ tot;
    26         int nw = i;
    27         while(!vis[nw]) ++ d[tot], vis[nw] = true, nw = a[x][nw];
    28     }
    29     memset(f, 0, sizeof(f));
    30     f[0][0][0] = 1;
    31     for(int l = 1 ; l <= tot ; ++ l) {
    32         for(int i = s1 ; i >= 0 ; -- i) {
    33             for(int j = s2 ; j >= 0 ; -- j) {
    34                 for(int k = s3 ; k >= 0 ; -- k) {
    35                     if(i>=d[l]) (f[i][j][k] += f[i-d[l]][j][k]) %= p;
    36                     if(j>=d[l]) (f[i][j][k] += f[i][j-d[l]][k]) %= p;
    37                     if(k>=d[l]) (f[i][j][k] += f[i][j][k-d[l]]) %= p;
    38                 }
    39             }
    40         }
    41     }
    42     return f[s1][s2][s3];
    43 }
    44 
    45 int main() {
    46     scanf("%d%d%d%d%d", &s1, &s2, &s3, &m, &p);
    47     n = s1+s2+s3;
    48     for(int i = 1 ; i <= m ; ++ i) {
    49         for(int j = 1 ; j <= n ; ++ j) scanf("%d", &a[i][j]);
    50     }
    51     ++ m;
    52     for(int i = 1 ; i <= n ; ++ i) a[m][i] = i;
    53     int ans = 0;
    54     for(int i = 1 ; i <= m ; ++ i) {
    55         ans += Dp(i);
    56         if(ans>p) ans -= p;
    57     }
    58     ans = (ans*Ksm(m, p-2, p))%p;
    59     printf("%d", ans);
    60     return 0;
    61 }
    View Code
  • 相关阅读:
    [转]wireshark 实用过滤表达式(针对ip、协议、端口、长度和内容) 实例介绍
    [转]HTTPS连接的前几毫秒发生了什么
    将生成的数据写入文件
    linux查看网络监听端口
    [转] Linux下移动virtualbox虚拟硬盘丢失eth0
    sockaddr结构体
    以十六进制形式打印字符串
    pta5-9 Huffman Codes (30分)
    pat1068. Find More Coins (30)
    hduoj 2955Robberies
  • 原文地址:https://www.cnblogs.com/assassain/p/5439308.html
Copyright © 2011-2022 走看看