zoukankan      html  css  js  c++  java
  • BZOJ 1004: [HNOI2008]Cards( 置换群 + burnside引理 + 背包dp + 乘法逆元 )

    题意保证了是一个置换群.

    根据burnside引理, 答案为Σc(f) / (M+1). c(f)表示置换f的不动点数, 而题目限制了颜色的数量, 所以还得满足题目, 用背包dp来计算.dp(x,i,j,k) = dp(x,i-cntx,j,k)+dp(x,i,j-cntx,k)+dp(x,i,j,k-cntx)表示前x个置换红蓝绿个用了i,j,k次,cntx表示第x个置换的循环数. 然后最后乘(M+1)的乘法逆元就OK了.

    ----------------------------------------------------------------------------

    #include<bits/stdc++.h>
     
    using namespace std;
     
    const int maxn = 69;
    const int _maxn = 29;
     
    int R, B, G, M, N, MOD, p[maxn];
    int T, dp[2][_maxn][_maxn][_maxn], cnt[maxn], n, vis[maxn];
     
    void calculate() {
    n = 0;
    for(int i = 0; i < N; i++) if(vis[i] != T) {
    cnt[n] = 1;
    for(int j = p[i]; !vis[j]; vis[j] = T, cnt[n]++, j = p[j]);
    n++;
    }
    }
     
    void gcd(int a, int b, int& d, int& x, int& y) {
    if(!b) {
    d = a;
    x = 1;
    y = 0;
    } else {
    gcd(b, a % b, d, y, x);
    y -= x * (a / b);
    }
    }
     
    int inv() {
    int d, x, y;
    gcd(M + 1, MOD, d, x, y);
    return (x + MOD) % MOD;
    }
     
    int main() {
    memset(vis, -1, sizeof vis);
    scanf("%d%d%d%d%d", &R, &B, &G, &M, &MOD);
    N = R + B + G;
    for(T = 0; T < M; T++) {
    for(int i = 0; i < N; i++)
    scanf("%d", p + i);
    calculate();
    }
    memset(dp, 0, sizeof dp);
    int c = 0, p = 1;
    dp[c][0][0][0] = 1;
    for(int i = 0; i < n; i++) {
    swap(c, p);
    memset(dp[c], 0, sizeof dp[c]);
    for(int r = 0; r <= R; r++)
    for(int b = 0; b <= B; b++)
    for(int g = 0; g <= G; g++) {
    if(r >= cnt[i]) dp[c][r][b][g] += dp[p][r - cnt[i]][b][g];
    if(b >= cnt[i]) dp[c][r][b][g] += dp[p][r][b - cnt[i]][g];
    if(g >= cnt[i]) dp[c][r][b][g] += dp[p][r][b][g - cnt[i]];
    while(dp[c][r][b][g] >= MOD) dp[c][r][b][g] -= MOD;
    }
    }
    int ans = dp[c][R][B][G] * inv() % MOD;
    printf("%d ", ans);
    return 0;
    }

    ----------------------------------------------------------------------------

    1004: [HNOI2008]Cards

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 2381  Solved: 1388
    [Submit][Status][Discuss]

    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。

    Source

  • 相关阅读:
    【目标检测】RCNN算法详解
    自己搭建传统ocr识别项目学习
    015. asp.net实现简易聊天室
    014. asp.net实现记住密码的功能
    013. asp.net统计网站访问人数
    012. asp.net生成验证码图片(汉字示例/字母+数字)
    011. asp.net内置对象
    010. 使用.net框架提供的属性
    001. 使用ssh连接不上centos 6.5的解决方法及其解决中文乱码
    009. C#中的WebBrowser控件的属性、方法及操作演示代码(转)
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4842541.html
Copyright © 2011-2022 走看看