Pólya 定理(草稿)
来源:互联网 发布:阿里云cdn加速oss 编辑:程序博客网 时间:2024/05/21 12:54
Pólya 定理
Polya 定理常在算法竞赛中用于解决计数问题。
首先介绍一下理解此定理需要的数学基础:
1 群
给定集合
2 置换群
置换:集合
置换乘积:令
例:
对于置换群
按照置换乘法的定义,有:S3={(112233),(112332),(122133),(122331),(132132),(132231)}
(122133)(132132)=(122133)(211332)=(112332)
上例中的置换表示方法虽然可用,但有两个显而易见的缺点,所以我们在这里引入另一种表示置换的方法:循环表示法
循环:
置换
将置换表示为若干循环乘积的方法:
(参考置换定义图)首先在这个置换的第一行任取一个元素,比如说a1 ,然后去a1 下面的元素σ(a1) ,接着取第一行σ(a1) 下面的元素,以此类推,知道渠道第一行某一元素下面的元素为a1 时为止。如果这次是索取的元素个数小于n 则从置换的第一行中去一个以前没有去过的元素重复以上操作,直到取遍第一行的所有元素为止。
-
例:
置换(122331465465) 可以写为(123)(456)
- 二阶循环
(ab) 叫做a 和b 的对换 - 如果两个循环中没有公共元素,则称这两个循环是不相交的。
我们有如下定理:任何一个置换都可以表示称若干个互不相交的循环的乘积,且表示方法是唯一的。
3 Burnside 引理
在计数问题中,常常有给出一些置换,求本质不同的方案数的类型,Burnside 引理解释用于解决此类问题的。
设
例:
已知S3={(112233),(112332),(122133),(122331),(132132),(132231)}={e,(23),(12),(123),(132),(13)}
将S3 中的元素依次记为g1,g2,g3,g4,g5,g6 ,则且Z1={e,(23)},Z2={e,(13)},Z3={e,(12)} λ1(g1)=3,λ1(g2)=λ1(g3)=λ1(g6)=1,λ1(g4)=λ1(g5)=0
Burnside 引理:
若
Burnside 引理的简单应用
3.1 [BZOJ1004]Cards[HNOI2008]
小春现在很清闲,面对书桌上的 N 张牌,他决定给每张染色,目前小春只有 3 种颜色:红色,蓝色,绿色。他询问 Sun 有多少种染色方案, Sun 很快就给出了答案。进一步,小春要求染出 Sr 张红色,Sb张蓝色,Sg张绝色。他又询问有多少种方案,Sun想了一下,又给出了正确答案。最后小春发明了 M 种不同的洗牌法,这里他又问Sun有多少种不同的染色方案。
两种染色方法相同当且仅当其中一种可以通过任意的洗牌法(即可以使用多种洗牌法,而每种方法可以使用多次)洗成另一种。 Sun 发现这个问题有点难度,决定交给你,答案可能很大,只要求出答案除以 P 的余数( P 为质数)。
100% 数据满足Max{Sr,Sb,Sg}≤20 。
本题就是 Burnside 引理的简单应用,利用 Burnside 引理,我们可以将问题转换为求每个洗牌方案(即置换)中的不变元个数,这里由于每个颜色个数有限制,所以可以用三维费用背包求。最后在输出答案的时候由于涉及到模意义下的除法可以用拓展欧几里得求逆元输出。
/************************************************************** Problem: 1004 User: zhangche0526 Language: C++ Result: Accepted Time:148 ms Memory:2652 kb****************************************************************/#include<iostream>#include<cstdio>#include<cstring>typedef long long ll;using namespace std;inline int read(){ int x=0;char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x;}int s1,s2,s3,n,m,P,ans;int a[70][70],f[70][70][70],d[70];bool b[70];int dp(int x){ for(int i=1;i<=n;i++)b[i]=0; int sum=0,p; for(int i=1;i<=n;i++) if(!b[i]) { d[++sum]=1;p=i; b[p]=1; while(!b[a[x][p]]) { d[sum]++; b[a[x][p]]=1; p=a[x][p]; } } for(int i=s1;i>=0;i--) for(int j=s2;j>=0;j--) for(int k=s3;k>=0;k--) f[i][j][k]=0; f[0][0][0]=1; for(int h=1;h<=sum;h++) for(int i=s1;i>=0;i--) for(int j=s2;j>=0;j--) for(int k=s3;k>=0;k--) { if(i>=d[h])f[i][j][k]=(f[i][j][k]+f[i-d[h]][j][k])%P; if(j>=d[h])f[i][j][k]=(f[i][j][k]+f[i][j-d[h]][k])%P; if(k>=d[h])f[i][j][k]=(f[i][j][k]+f[i][j][k-d[h]])%P; } return f[s1][s2][s3];}void exgcd(int a,int b,int &x,int &y){ if(b==0){x=1;y=0;return;} exgcd(b,a%b,x,y); int t=x;x=y;y=t-a/b*y;}int main(){ s1=read(),s2=read(),s3=read(),m=read(),P=read(); n=s1+s2+s3; for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) a[i][j]=read(); m++; for(int i=1;i<=n;i++)a[m][i]=i; for(int i=1;i<=m;i++) ans=(ans+dp(i))%P; int x,y; exgcd(m,P,x,y); while(x<=0)x+=P,y-=m; printf("%d",ans*x%P); return 0;}
4 Pólya 定理
在上文提到过,任何一个置换都可以表示成若干个互不相交的循环的成积,且表示的方法是唯一的。
在一个置换
设
又
故还可以写成
参考文献
[1] 林厚从. 信息学竞赛之数学一本通[M]. 南京:东南大学出版社, 2016. 64-90
[2] 吴文虎, 孙贺. 程序设计中的组合数学[M]. 北京:清华大学出版社, 2005. 130-144
[3] wzq_QwQ. BZOJ 1004 [HNOI2008]Cards 置换+burnside定理+逆元[EB/OL]. http://blog.csdn.net/wzq_QwQ/article/details/47041031, 2015-07-24
- Pólya 定理(草稿)
- Pólya定理初探
- sgu208:Toral Tickets(Pólya定理)
- POJ1286,2409——Let it Bead,Necklace of Beads( Pólya定理)
- POJ2154(Pólya定理与欧拉函数优化)
- POJ2154(Pólya定理与欧拉函数优化)
- POJ 2409 Let it Bead Pólya定理
- POJ-2154-Color(Pólya)
- Pólya计数小结
- Pólya计数法的应用
- 【Pólya计数】hnoi2009图的同构计数
- 【有限制的 Pólya+矩阵快速幂】poj2888
- Burnside引理和Pólya计数法
- 【等价的穿越】Burnside引理&Pólya计数法
- 【SPOJ-TRANSP2】Transposing is Even More Fun【Pólya】【欧拉函数】【二进制】
- 【SPOJ-TRANSP】Transposing is Fun【Pólya】【欧拉函数】【二进制】
- 【Burnside引理】【Pólya计数法】【Pollard's Rho】【JZOJ 5457】 项链
- 【证明】关于项链问题中旋转操作的置换群的循环节个数、长度的证明【Pólya】【同余】
- 背包九讲
- 【生活感悟】达克效应--要自信不要自负,越努力越幸运
- 计蒜客第四场 A(搜索)
- 状态模式
- java基础--求数组中的最值
- Pólya 定理(草稿)
- 阿里物联网套件-服务端SDK学习实践(基础篇-12推送数据给设备并得到响应)
- 《现代操作系统(中文第三版)》课后习题——第六章 死锁
- 布林曲线函数中的MA_Type
- java基础--逆序输出数组元素
- 微信小程序学习第一天——js注册程序(逻辑层)
- 社交数据初探汇总
- LeetCode 120. Triangle
- Windows版apache服务器下载