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。

思路

嘛~首先可以看到是组合数学的题目。之后就想大概是个什么模型。

看到在一个排列中元素可以交换,就想到了置换群,Polya计数法。

那么就是有这么多给你的置换方法,求本质上不同的排列有多少。我们将每一个置换群分解,找出置换的循环节:

比如置换1 4 3 5 2可以分解为(1)(2 4 5)(3)这三个循环节。

由polya计数法得:ans=所有置换中本质相同的方案的平均数。

看到100%数据满足 Max{Sr,Sb,Sg}<=20可以用dp做。

用f[i][j][k]表示用了i个红色,j个绿色,k个蓝色的方案数,则f[i][j][k]=f[i-size][j][k]+f[i][j-size][k]+f[i][j][k-size](size是当前循环节的大小)

最后不要忘记加上(1 2 3 ....n)这个循环,这个可以直接算出有N!/(sr!*sg!*sb!)

然后除以m+1,p为质数,用逆元算。

 #include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#include <vector>
#include <ctime>
#include <functional>
#define pritnf printf
#define scafn scanf
#define For(i,j,k) for(int i=(j);i<=(k);(i)++)
#define Clear(a) memset(a,0,sizeof(a))
using namespace std;
typedef long long LL;
typedef unsigned int Uint;
const int INF=0x7fffffff;
//==============struct declaration============== //==============var declaration=================
const int MAXN=;
int sr,sb,sg,n,m,p,MOD,cnt=;
int ans=;
int tran[MAXN*];
int f[MAXN][MAXN][MAXN];
bool vis[MAXN*];
//==============function declaration============
int quickpow(int a,int Exp);
int inv(int a){return quickpow(a,MOD-);}
int fact(int x){int ans=;for(int i=;i<=x;i++) ans=(ans*i)%MOD;return ans;}
//==============main code=======================
int main()
{
//#define FILE__
#ifdef FILE__
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
scanf("%d%d%d%d%d",&sr,&sb,&sg,&m,&MOD);n=sr+sb+sg;
for(int i=;i<=m;i++){
for(int j=;j<=n;j++)
scanf("%d",tran+j);
memset(vis,false,sizeof(vis));memset(f,,sizeof(f));
f[][][]=;cnt=;
for(int p=;p<=n;p++){
if (vis[p]) continue;
cnt++;
int siz=,x=p;
while (!vis[x]){
vis[x]=true;
x=tran[x];
siz++;
}//找出循环节
for(int i=sr;i>=;i--)
for(int j=sb;j>=;j--)
for(int k=sg;k>=;k--){
if (i>=siz) f[i][j][k]+=f[i-siz][j][k];
if (j>=siz) f[i][j][k]+=f[i][j-siz][k];
if (k>=siz) f[i][j][k]+-f[i][j][k-siz];
f[i][j][k]%=MOD;
} //DP
}
ans=(ans+f[sr][sb][sg])%MOD;
}
ans=ans+fact(n)*inv(fact(sr))*inv(fact(sb))*inv(fact(sg));
printf("%d\n",(ans*inv(m+))%MOD);
return ;
}
//================fuction code====================
int quickpow(int a,int Exp){
if (Exp==) return ;
if (Exp==) return a;
int temp=quickpow(a,Exp/);
temp=(temp*temp)%MOD;
if (Exp&) temp=(temp*a)%MOD;
return temp;
}

Code

【HNOI2008】Cards BZOJ 1004的更多相关文章

  1. 【BZOJ】【1004】【HNOI2008】Cards

    Burnside/Polya+背包DP 这道题目是等价类计数裸题吧……>_> 题解:http://m.blog.csdn.net/blog/njlcazl_11109/8316340 啊其 ...

  2. BZOJ 1004 【HNOI2008】 Cards

    题目链接:Cards 听说这道题是染色问题的入门题,于是就去学了一下\(Bunside\)引理和\(P\acute{o}lya\)定理(其实还是没有懂),回来写这道题. 由于题目中保证"任意 ...

  3. 【BZOJ1004】【HNOI2008】Cards 群论 置换 burnside引理 背包DP

    题目描述 有\(n\)张卡牌,要求你给这些卡牌染上RGB三种颜色,\(r\)张红色,\(g\)张绿色,\(b\)张蓝色. 还有\(m\)种洗牌方法,每种洗牌方法是一种置换.保证任意多次洗牌都可用这\( ...

  4. 【BZOJ1010】【HNOI2008】玩具装箱(斜率优化,动态规划)

    [BZOJ1010][HNOI2008]玩具装箱 题面 题目描述 P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一 ...

  5. 【BZOJ1004】Cards(组合数学,Burnside引理)

    [BZOJ1004]Cards(组合数学,Burnside引理) 题面 Description 小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Su ...

  6. Cards BZOJ 1004

    Cards [问题描述] 小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有多少种染色方案,Sun很快就给出了答案.进一步,小春要求染出Sr张 ...

  7. 【BZOJ】【1009】 【HNOI2008】GT考试

    DP/KMP/矩阵乘法 好神的题啊……跪了跪了 $n\leq 10^9$是什么鬼……我们还是先不要考虑这个鬼畜的玩意了>_> 用类似数位DP的思路,我们可以想到一个DP方程:$f[i][j ...

  8. 【BZOJ】【1010】【HNOI2008】玩具装箱Toy

    DP/斜率优化 根据题目描述很容易列出动规方程:$$ f[i]=min\{ f[j]+(s[i]-s[j]+i-j-1-L)^2 \}$$ 其中 $$s[i]=\sum_{k=1}^{i} c[k] ...

  9. 【BZOJ】【1005】【HNOI2008】明明的烦恼

    Prufer序列/排列组合+高精度 窝不会告诉你我是先做了BZOJ1211然后才来做这题的>_>(为什么?因为我以前不会高精度呀……) 在A了BZOJ 1211和1089之后,蒟蒻终于有信 ...

随机推荐

  1. vuejs的动态过滤

    想要通过vuejs动态过滤(这里动态指得是过滤的条件是动态变化的), 一直没找到好办法, 最蠢的办法当然是两个两个数组,一个作为原始副本数组 一个作为视图数组,这样当过滤条件变化的时候 动态拷贝原始数 ...

  2. StackExchange.Redis 访问封装类

    最近需要在C#中使用Redis,在Redis的官网找到了ServiceStack.Redis,最后在测试的时候发现这是个坑,4.0已上已经收费,后面只好找到3系列的最终版本,最后测试发现还是有BUG或 ...

  3. mybatis 使用经验小结

    一.多数据源问题 主要思路是把dataSource.sqlSesstionFactory.MapperScannerConfigurer在配置中区分开,各Mapper对应的包名.类名区分开 <? ...

  4. 创意十足的web布局及交互设计

    富有灵感和创意的设计与一般设计的区别在于,它不那么容易被想到和实现,一旦它被实现,一个非常有趣并且迷人的网站就诞生了. 网站几乎每天都能见到,但是不是每一个网站你都会说“真希望我也能想到过!” 设计者 ...

  5. Memcached 服务器端命令

    memcached的基本命令(安装.卸载.启动.配置相关): -p 监听的端口   -l 连接的IP地址, 默认是本机    -d start 启动memcached服务   -d restart 重 ...

  6. 【JavaScript】冒泡排序,字符串排序,数字排序

    原理:是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换, function bubbleClick() { var str = "50,1,4,6,9,76,43,22,2, ...

  7. 77 swapoff-关闭系统交换区

    Linux swapoff命令用于关闭系统交换区(swap area). swapoff实际上为swapon的符号连接,可用来关闭系统的交换区. 语法 swapoff [设备] 参数: -a 将/et ...

  8. iOS学习-KVO设计模式

    KVO 即Key-Value Observing  键-值观察的缩写,简单的说就是通过键来观察一个对象属性值的变化.当这个被观察的属性发生变化时,观察者就会收到通知(观察者可以是这个对象本身,也可以是 ...

  9. iOS 如何打开后灯(闪光灯)

    - (void)torchOnOrOff { AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMedia ...

  10. AI贪吃蛇(二)

    前言 之前写过一篇关于贪吃蛇AI的博客,当时虽然取得了一些成果,但是也存在许多问题,所以最近又花了三天时间重新思考了一下.以下是之前博客存在的一些问题: 策略不对,只要存在找不到尾巴的情况就可能失败, ...