BZOJ 1004 HNOI 2008 Cards Burnside引理

题目大意:给出一个置换群,求有多少种本质不同的染色方案。

思路:Burnside引理:置换群的等价类数目=所有置换的不动点数目的平均值。

有了这个引理,我们只需要求出所有不动点的数目求一个平均值就可以的到等价类的数目了。

要使一种染色的方案在一种置换的意义下是不动点,需要让这个置换的每个循环节中的颜色都相同。先求出所有置换的循环,然后用一个背包就可以初解了。最后乘法逆元搞一下除法。

CODE:

#define _CRT_SECURE_NO_DEPRECATE

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 110
using namespace std;

int R,G,B,cnt;
int displace,p;

struct Displace{
    int change[MAX];
    int loop[MAX],loops;
    bool v[MAX];

    void Read() {
        for(int i = 1; i <= cnt; ++i)
            scanf("%d",&change[i]);
    }
    void DFS(int x,int deep) {
        if(v[x])    throw deep;
        v[x] = true;
        DFS(change[x],deep + 1);
    }
    void GetLoop() {
        for(int i = 1; i <= cnt; ++i)
            if(!v[i]) {
                try{
                    DFS(i,0);
                }catch(int len) {
                    loop[++loops] = len;
                }
            }
    }
}src[MAX];

int f[MAX][MAX][MAX];

inline int Power(int x,int y)
{
    int re = 1;
    while(y) {
        if(y&1) re = (re * x) % p;
        y >>= 1;
        x = (x * x) % p;
    }
    return re;
}

int main()
{
    cin >> R >> G >> B >> displace >> p;
    cnt = R + G + B;
    for(int i = 1; i <= displace; ++i)
        src[i].Read();
    ++displace;
    for(int i = 1; i <= cnt; ++i)
        src[displace].change[i] = i;
    for(int i = 1; i <= displace; ++i)
        src[i].GetLoop();
    int total = 0;
    for(int i = 1; i <= displace; ++i) {
        memset(f,0,sizeof(f));
        f[0][0][0] = 1;
        for(int j = 1; j <= src[i].loops; ++j)
            for(int r = R; ~r; --r)
                for(int b = B; ~b; --b)
                    for(int g = G; ~g; --g) {
                        if(r - src[i].loop[j] >= 0)  f[r][g][b] += f[r - src[i].loop[j]][g][b];
                        if(g - src[i].loop[j] >= 0)  f[r][g][b] += f[r][g - src[i].loop[j]][b];
                        if(b - src[i].loop[j] >= 0)  f[r][g][b] += f[r][g][b - src[i].loop[j]];
                        f[r][g][b] %= p;
                    }
        total += f[R][G][B];
    }
    cout << total * Power(displace,p - 2) % p << endl;
    return 0;
}

时间: 2024-10-18 17:07:00

BZOJ 1004 HNOI 2008 Cards Burnside引理的相关文章

BZOJ 1004 HNOI2008 Cards Burnside引理

题目大意:给定n张卡牌和m个置换,求等价类个数 数据保证这m个置换加上自身置换后构成一个置换群 BZOJ坑爹0.0 这么重要的条件不给出来尼玛怎么做 Burnside引理--昨晚为了做这题硬啃了一晚上白书0.0 都快啃吐了0.0 Burnside引理:一个置换群下的等价类个数等于所有置换的不动点个数的平均值 没有接触过群论的建议去啃白书-- 网上的东西看不懂的 最后那个除法要用乘法逆元 我懒得写EXGCD写了费马小定理0.0 #include<cstdio> #include<cstri

[BZOJ1004](HNOI 2008) Cards

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

【BZOJ1004】[HNOI2008]Cards Burnside引理

[BZOJ1004][HNOI2008]Cards 题意:把$n$张牌染成$a,b,c$,3种颜色.其中颜色为$a,b,c$的牌的数量分别为$sa,sb,sc$.并且给出$m$个置换,保证这$m$个置换加上本身的置换能构成一个置换群,两种染色方案被认为是相同的当且仅当一种方案可以通过某个置换变成另一种.求不同的染色方案数.答案对$P$取模. $sa,sb,sc\le 20,m\le 60$ 题解:这里对每种颜色都有一个限制,怎么办呢? 回顾从Burnside引理到Pólya定理的推导过程. 如果

bzoj1004: [HNOI2008]Cards Burnside引理+01背包

三维01背包算出在每一个置换下不变的染色方案数,Burnside引理计算答案. PS:数据太水所以只算恒等置换也是可以过的. #include<bits/stdc++.h> using namespace std; int n,m,p,x,y,z; bool u[61]; int f[21][21][21],s[61],v[61]; int power(int u,int v){ int d=1; for(;v;v>>=1){ if(v&1) d=d*u%p; u=u*u%

bzoj1004: [HNOI2008]Cards(burnside引理+DP)

题目大意:3种颜色,每种染si个,有m个置换,求所有本质不同的染色方案数. 置换群的burnside引理,还有个Pólya过几天再看看... burnside引理:有m个置换k种颜色,所有本质不同的染色方案数就是每种置换的不变元素的个数的平均数. 求每种置换的不变元素的个数用背包解决.因为置换之后元素不变,所以对于每个循环节我们要染一个颜色,于是先处理出循环节作为背包中的"物体",然后一个三维背包解决.f[i][j][k]的i j k表示三种颜色分别还可以染多少次. 除m%p用费马小定

【bzoj1004】[HNOI2008]Cards Burnside引理+背包dp

题目描述 用三种颜色染一个长度为 $n=Sr+Sb+Sg$ 序列,要求三种颜色分别有 $Sr,Sb,Sg$ 个.给出 $m$ 个置换,保证这 $m$ 个置换和置换 ${1,2,3,...,n\choose 1,2,3,...,n}$ 构成一个置换群,求置换后不同构的序列个数模 $p$ . $0\le Sr,Sb,Sg\le 20,0\le m\le 60,m+1\le p\le 100$ ,$p$ 是质数. 输入 第一行输入 5 个整数:Sr,Sb,Sg,m,p(m<=60,m+1<p<

[BZOJ 1008] [HNOI 2008] 越狱

1008: [HNOI2008]越狱 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 5041  Solved: 2177[Submit][Status][Discuss] Description 监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种.如果相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱 Input 输入两个整数M,N.1<=M<=10^8,1<=N<=10

[BZOJ 1010][HNOI 2008] 玩具装箱toy

比较基础的斜率优化DP详见以下2篇博客 http://www.cnblogs.com/proverbs/archive/2012/10/06/2713109.html http://blog.163.com/myq_952/blog/static/863906320112711750378/ 主要总结斜率优化时的步骤 1.证明较优决策点对后续状态影响的持续性 2.求斜率方程:一般化为左边是J,K,右边是I的形式 3.规定队列的维护规则 4.看决策是否又单调性,没有的话有应该怎样维护 本题的代码

BZOJ 1009 HNOI 2008 GT考试 AC自动机+矩阵乘法

题目大意:给出一个不能出现的字符串,问长度为k的字符串有多少种. 思路:用给定串建立一个AC自动机(或者KMP随便了),然后跑矩阵乘法就行了. CODE: #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int k,length,p; char s[MAX]; in