zoukankan      html  css  js  c++  java
  • bzoj 1004 Cards

    1004: [HNOI2008]Cards

    Description

    小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有
    多少种染色方案,Sun很快就给出了答案.进一步,小春要求染出Sr张红色,Sb张蓝色,Sg张绝色.他又询问有多少种方
    案,Sun想了一下,又给出了正确答案. 最后小春发明了M种不同的洗牌法,这里他又问Sun有多少种不同的染色方案.
    两种染色方法相同当且仅当其中一种可以通过任意的洗牌法(即可以使用多种洗牌法,而每种方法可以使用多次)洗
    成另一种.Sun发现这个问题有点难度,决定交给你,答案可能很大,只要求出答案除以P的余数(P为质数).

    Input

    第一行输入5个整数:Sr,Sb,Sg,m,p(m<=60,m+1<p<100)。n=Sr+Sb+Sg。接下来m行,每行描述一种洗牌法,每行有n个用空格隔开的整数X1X2...Xn,恰为1到n的一个排列,表示使用这种洗牌法,第i位变为原来的Xi位的牌。输入数据保证任意多次洗牌都可用这m种洗牌法中的一种代替,且对每种洗牌法,都存在一种洗牌法使得能回到原状态。

    Output

    不同染法除以P的余数

    Sample Input

    1 1 1 2 7

    2 3 1

    3 1 2

    Sample Output

    2

    HINT

    有2 种本质上不同的染色法RGB 和RBG,使用洗牌法231 一次可得GBR 和BGR,使用洗牌法312 一次可得BRG 和GRB。

    100%数据满足 Max{Sr,Sb,Sg}<=20。

    题解

    此题我一开始看,没有半点思路,还以为是图论。后来,我去搜题解,说是裸题。当时我就怒了,觉得自己连裸题都做不出来。怼了好久之后怂了,又去看题解,群论裸题

    首先此题需要burnside定理,即在集合(X)上的群(G),对于(g in G),令(X^g)为在(g)作用下的不动元素,有(|X/G|={1 over {|G|}} sum_{g in G}|X^g|)

    在此题中就可以得出(Ans = sum Cal(change_i) * |G|^{-1}),其中(Cal)计算每种置换的方案数。

    Ps:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    const int N = 65, M = 105;
    int n, m, p, sr, sb, sg;
    int dp[N][N][N], cha[M][N], d[N];
    bool vis[N];
    #define Inc(a,b) ((a) = ((a) + (b))%p)
    int Cal(const int &x) {
        memset(dp, 0, sizeof dp); 
        memset(vis, 0, sizeof vis);
        int Sum = 0, t;
        for (int i = 1; i <= n; ++i) 
        if (!vis[i]) {
            d[++Sum] = 1; vis[t = i] = true;
            while (!vis[cha[x][t]]) {
                ++d[Sum]; t = cha[x][t];
                vis[t] = true;
            }
        }
        dp[0][0][0] = 1;
        for (t = 1; t <= Sum; ++t)
          for (int i = sr; ~i; --i)
            for (int j = sb; ~j; --j)
              for (int k = sg; ~k; --k) {
                  if (i >= d[t]) Inc(dp[i][j][k], dp[i-d[t]][j][k]);
                  if (j >= d[t]) Inc(dp[i][j][k], dp[i][j-d[t]][k]);
                  if (k >= d[t]) Inc(dp[i][j][k], dp[i][j][k-d[t]]);
              }
        //printf("%d
    ", dp[sr][sb][sg]);
        return dp[sr][sb][sg];
    }
     
    long long Mod_Pow(long long b, int c) {
        long long ans = 1LL;
        while (c) {
            if (c&1) ans = ans * b % p;
            b = b * b % p;
            c >>= 1;
        }
        return ans;
    }
     
    int main() {
        scanf("%d%d%d%d%d", &sr, &sb, &sg, &m, &p);
        n = sr + sb + sg;
        for (int i = 1; i <= m; ++i)
          for (int j = 1; j <= n; ++j)
            scanf("%d", cha[i] + j);
        ++m;
        long long ans = 0;
        for (int i = 1; i <= n; ++i) cha[m][i] = i;
        for (int i = 1; i <= m; ++i) Inc(ans, Cal(i));
        //printf("%d
    ", ans);
        ans = ans * Mod_Pow(m, p - 2) % p;
        printf("%lld
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    pam_smb
    什么是PAM认证
    如何使windows7的默认共享可以被访问[转载]
    remote mounting from windows to linux
    Kernel boot options
    Linux kernel启动选项(参数)
    tftp client命令示例
    在不同的Linux发行版上安装TFTP Server
    SpringBoot2 整合Nacos组件,环境搭建和入门案例详解
    我是如何做到springboot自动配置原理解析
  • 原文地址:https://www.cnblogs.com/cycleke/p/5877435.html
Copyright © 2011-2022 走看看