码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 1004 HNOI 2008 Cards Burnside引理

时间:2015-01-23 09:34:44      阅读:213      评论:0      收藏:0      [点我收藏+]

标签:bzoj   群论   buruside引理   hnoi 2008   

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


思路: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;
}


BZOJ 1004 HNOI 2008 Cards Burnside引理

标签:bzoj   群论   buruside引理   hnoi 2008   

原文地址:http://blog.csdn.net/jiangyuze831/article/details/43051041

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!