一、Burnside引理
二、Polya定理
三、应用
简单
题意:n个珠子串成一个项链,用三种颜色去涂色。问一共有多少种不同的涂色方法。经过翻转和旋转得到相同项链的视为相同的涂色方法。
思路:Polya模板题,只是m等于3已给出。
(1)旋转。每次旋转一格,共旋转n次。每次将项链旋转i格后,其循环节数为gcd(n,i)。
(2)翻转。分奇偶讨论。
n为奇数时,如图右,对称轴是一个珠子到圆心的连线,一共n条。选定对称轴后,对称轴上的一个珠子构成一个循环,其他n-1个珠子分别以对称轴对称构成(n-1)/2个循环,所以循环节的个数是 1 + (n – 1) / 2 = (n + 1) / 2 。故共有n个循环节数为(n+1)/2的循环群。
n为偶数时,如图左,对称轴可能是两个珠子的连线,一共 n / 2条。选定对称轴后,对称轴上的两个珠子构成两个循环,其他n-2个珠子分别以对称轴对称构成(n-2)/2个循环,循环节个数为2+(n-2)/2=(n+2)2/;对称轴还可能是两个珠子的中点和圆心的连线,所有珠子两两对称,构成n / 2 个循环。 故共有n/2个循环节数为(n+2)/2的循环群,和n/2个循环节数为n/2的循环群。
值得注意的是,旋转加翻转共有2n次置换,故共有2n个置换群,即|G|=2*n.
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long LL;
const int m = 3;
int gcd (int a,int b){
if (b==0)
return a;
return gcd(b,a%b);
}
LL Polya(int n){
LL ret=0;
for(int i=1;i<=n;i++)
ret+=pow(m,gcd(n,i));
if(n&1) ret+=n*pow(m,n/2+1);
else ret+=n/2*(pow(m,n/2)+pow(m,n/2+1));
ret/=2*n;
return ret;
}
int main(){
int n;
while(scanf("%d",&n)&&n!=-1){
if(n==0) puts("0");
else printf("%lld\n",Polya(n));
}
return 0;
}
和上题唯一的不同是m属于输入部分。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long LL;
int gcd (int a,int b){
if (b==0)
return a;
return gcd(b,a%b);
}
LL Polya(int m,int n){
LL ret=0;
for(int i=1;i<=n;i++)
ret+=pow(m,gcd(n,i));
if(n&1) ret+=n*pow(m,n/2+1);
else ret+=n/2*(pow(m,n/2)+pow(m,n/2+1));
ret/=2*n;
return ret;
}
int main(){
int m,n;
while(scanf("%d%d",&m,&n)&&(m&&n)){
printf("%lld\n",Polya(m,n));
}