Burnside定理与Polya定理

Burnside定理与Polya定理

关于置换群的定理。

求一些本质不同的方案数。

设一个状态\(S\),若他能通过一些置换到达状态\(T\),则它们是本质相同的。

首先将一些置换变成一次置换:比如一个正方形每次可以旋转\(90\)度,可以转换成只旋转一次,每次可以转\(360,270,180,90\),可以看作是作用在格子上的一些置换。

假设你可以对一个状态\(S\),做一些操作,求本质不同的结果个数。

一个结论(轨道-稳定子 定理):

本质不同的状态数为,所有置换的不动点的平均值。

设一个置换\(g\),\(F_g\)表示有多少状态\(S\)通过\(F_g\)依旧是\(S\)

则本质不同的方案数为\(1/|G|*\sum_{g\in G} F_g\)

polya 定理

其实是Burnside定理的特殊情况,针对染色问题。

设颜色数是\(k\)

一个置换可以看作一个有向图内有一堆环,设有\(m\)个环,则不动点的方案数为\(k^m\)

例题:

darkbzoj 3113

/*
{
######################
#       Author       #
#        Gary        #
#        2021        #
######################
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
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<<1)+(x<<3)+(ch^48);
//        ch=getchar();
//    }
//    return x;
//}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
LL n,m;
LL mul(LL A,LL B){
	LL res = 0;
    while (B) {
        if (B & 1) {
            res += A;
            if (res >= m) res -= m;
        }
        A += A;
        if (A >= m) A -= m;
        B >>= 1;
    }
    return res;
}
struct mat{
	LL a[3][3];
	mat (){
		memset(a,0,sizeof(a));
	}
	mat operator * (mat oth){
		mat ret;
		rep(i,3)
			rep(j,3)
				rep(k,3)
					(ret.a[i][j]+=mul(a[i][k],oth.a[k][j]))%=m;
		return ret;
	}
	mat operator ^ (int num){
		mat ret;
		rep(i,3) ret.a[i][i]=1;
		mat tmp=(*this);
		while(num){
			if(num&1) ret=ret*tmp;
			tmp=tmp*tmp;
			num>>=1;
		}
		return ret;
	}
};
mat tran;
LL f(int i){
	if(i==1) return 1;
	if(i==2) return 5;
	mat tmp=tran^(i-2);
	return (5ll*tmp.a[0][0]%m+tmp.a[1][0]+2ll*tmp.a[2][0])%m;
}
int phi_[31625+3];
vector<int> pri;
int phi(int x){
	if(x<=31625) return phi_[x];
	int ret=x;
	for(auto it:pri){
		if(it*it>x) break;
		if(x%it==0){
			ret/=it;
			ret*=it-1;
			while(x%it==0) x/=it;
		}
	}
	if(x!=1) ret/=x,ret*=x-1;
	return ret; 
}
int main(){
//	freopen("test.in","r",stdin);
	phi_[1]=1;
	rb(i,2,31625){
		if(!phi_[i]){
			phi_[i]=i-1;
			pri.PB(i);
		}
		for(auto it:pri){
			if(it*i>31625) break;
			if(i%it){
				phi_[i*it]=phi_[i]*(it-1);
			}
			else{
				phi_[i*it]=phi_[i]*it;
				break;
			}
		}
	}
	while(scanf("%lld%lld",&n,&m)!=EOF){
		m*=n;
		tran.a[0][0]=3;
		tran.a[1][0]=m-1;
		tran.a[2][0]=1;
		tran.a[0][1]=1;
		tran.a[2][2]=1;
		LL ret=0;
		for(int i=1;i*i<=n;++i){
			if(n%i==0){
				(ret+=mul(f(i),phi(n/i)))%=m;
				if(i*i!=n){
					(ret+=mul(f(n/i),phi(i)))%=m;
				}
			}
		}
		ret/=n;
		printf("%lld\n",ret);
	}
	return 0;
}
posted @ 2021-03-18 10:32  WWW~~~  阅读(75)  评论(0编辑  收藏  举报