bzoj 1004 Cards 组合计数

这道题考察的是组合计数(用Burnside,当然也可以认为是Polya的变形,毕竟Polya是Burnside推导出来的)。

这一类问题的本质是计算置换群(A,P)中不动点个数!(所谓不动点,是一个二元组(a,p),a∈A,p∈P ,使得p(a)=a,即a在置换p的作用后还是a)。

Polya定理其实就是告诉了我们一类问题的不动点数的计算方法。

对于Burnside定理的考察,我见过的有以下几种形式(但归根结底还是计算不动点数):

  1、限制a(a∈A)的特点,本题即是如此(限制了各颜色个数,可以用DP来统计(以前我们直接用c^k来计算某置换的不动点,c是颜色总数,k是循环节个数))

  2、让P的数量高出暴力的范围,(比如经典的项链染色问题,或者P就是一个对称群(包含所有置换)),此时就必须寻找数学规律,不能硬来。项链染色这种可以用欧拉函数优化;对于图的同构计数(它的置换群是一个对称群),先将置换按照其格式分类(见《组合数学》,可以想象具有相同格式的置换的不动点也是相同的),然后再观察某一特定格式的置换的不动点数是多少(是有规律的)。

注:应用定理解题时要保证置换成群,本题中,结合律是肯定的,输入说明中已经说了,该置换集合满足:封闭性,逆元,所以我们自己再添一个单位元((1)(2)...(m))就行了。

 1 /**************************************************************
 2     Problem: 1004
 3     User: idy002
 4     Language: C++
 5     Result: Accepted
 6     Time:116 ms
 7     Memory:844 kb
 8 ****************************************************************/
 9
10 #include <cstdio>
11 #include <cstring>
12 #define maxn 65
13 using namespace std;
14
15 int mpow( int a, int b, int n ) {
16     a %= n;
17     int rt;
18     for( rt=1; b; b>>=1,a=(a*a)%n )
19         if( b&1 ) rt=(rt*a)%n;
20     return rt;
21 }
22 int inv( int a, int n ) {
23     return mpow(a,n-2,n);
24 }
25
26 int sp[maxn], tot;
27 bool vis[maxn];
28 void split( int n, int *a ) {
29     tot = 0;
30     memset( vis, 0, sizeof(vis) );
31     for( int i=1; i<=n; i++ ) {
32         if( vis[i] ) continue;
33         tot++;
34         sp[tot] = 0;
35         int cur = i;
36         do {
37             sp[tot]++;
38             vis[cur] = true;
39             cur = a[cur];
40         } while( !vis[cur] );
41     }
42 }
43
44 int n, sr, sg, sb, m, p, ans;
45 int a[maxn];
46 int dp[21][21][21];
47
48 int dodp() {
49     memset( dp, 0, sizeof(dp) );
50     dp[0][0][0] = 1;
51     for( int i=1; i<=tot; i++ ) {
52         int sz = sp[i];
53         for( int r=sr; r>=0; r-- )
54             for( int g=sg; g>=0; g-- )
55                 for( int b=sb; b>=0; b-- ) {
56                     int & dv = dp[r][g][b];
57                     dv = 0;
58                     if( r>=sz ) dv += dp[r-sz][g][b];
59                     if( g>=sz ) dv += dp[r][g-sz][b];
60                     if( b>=sz ) dv += dp[r][g][b-sz];
61                     dv %= p;
62                 }
63     }
64     return dp[sr][sg][sb];
65 }
66 void update( int n, int *a ) {
67     split(n,a);
68     ans += dodp();
69     if( ans>p ) ans -= p;
70 }
71
72 int main() {
73     scanf( "%d%d%d%d%d", &sr, &sg, &sb, &m, &p );
74     n = sr+sg+sb;
75     for( int i=1; i<=m; i++ ) {
76         for( int j=1; j<=n; j++ )
77             scanf( "%d", a+j );
78         update(n,a);
79     }
80
81     for( int i=1; i<=n; i++ )
82         a[i] = i;
83     update(n,a);
84
85     ans *= inv(m+1,p);
86     ans %= p;
87     printf( "%d\n", ans );
88 }

推荐文章:

陈瑜希 《Pólya计数法的应用》

符文杰 《Pólya原理及其应用》

时间: 2024-10-02 09:45:49

bzoj 1004 Cards 组合计数的相关文章

BZOJ 1004 Cards

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

bzoj 1004 1004: [HNOI2008]Cards burnside定理

1004: [HNOI2008]Cards Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1668  Solved: 978[Submit][Status] Description 小 春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有多少种染色方案,Sun很快就给出了答 案.进一步,小春要求染出Sr张红色,Sb张蓝色,Sg张绝色.他又询问有多少种方案,Sun想了一下,又给出了正确答案. 最

[BZOJ 1004] [HNOI2008] Cards 【Burnside引理 + DP】

题目链接:BZOJ - 1004 题目分析 首先,几个定义和定理引理: 群:G是一个集合,*是定义在这个集合上的一个运算. 如果满足以下性质,那么(G, *)是一个群. 1)封闭性,对于任意 a, b 属于 G, a * b 属于 G 2)结合律, a * b * c = a * (b * c) 3)单位元,在 G 中存在一个单位元 e ,使得对于 G 中任意的 a , a * e = e * a = a 4)逆元, 对于 G 中任意的 a ,在 G 中存在 b , 使得 a * b = e ,

BZOJ 2111 Perm 排列计数(满二叉树)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2111 题意:求1到n有多少种排列满足:A[i]>A[i/2](2<=i<=n). 思路:形式类似二叉树.建模之后其实就是n个节点的不同的满二叉树有多少种?用f[i]表示i个节点的满二叉树个数,则f[n]=f[L]*f[R]*C(n-1,L).其中L和R对于确定的n来说是确定的.比如n=10时,左右子树分别有6.3个点. i64 a[N],n,p,f[N]; void init(

Yue Fei&#39;s Battle(组合计数递推)

//求一个直径为 k 的树有多少种形态,每个点的度不超过 3 // 非常完美的分析,学到了,就是要细细推,并且写的时候要细心 还有除法取模需要用逆元 #include <iostream> #include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> using namespace std; #define MOD 1000000007 #define L

POJ 1496 POJ 1850 组合计数

Code Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 8256 Accepted: 3906 Description Transmitting and memorizing information is a task that requires different coding systems for the best use of the available space. A well known system is t

POJ 3252 组合计数

Round Numbers Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 9149 Accepted: 3248 Description The cows, as you know, have no fingers or thumbs and thus are unable to play Scissors, Paper, Stone' (also known as 'Rock, Paper, Scissors', 'Ro,

HDU4675-GCD of Sequence(数论+组合计数)

GCD of Sequence Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 949    Accepted Submission(s): 284 Problem Description Alice is playing a game with Bob. Alice shows N integers a1, a2, -, aN, an

[HDU 3461] Saving Beans &amp; 组合计数Lucas定理模板

Saving Beans Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description Although winter is far away, squirrels have to work day and night to save beans. They need plenty of food to get through those long cold