[POJ2409]Let it Bead

求长度为 \(n\) 的环染色方案数,旋转翻转同构。


直接从 Polya 定理开始。

考虑一下这个置换群长怎么样:

发现可以用二元组 \((x,y) (x \in [0,n),y \in {0,1})\) 来描述每一个元素,表示旋转度数和是否翻转。

先考虑 \(y=0\),这是经典结论,循环数为 \(\gcd(x,n)\)

再考虑 \(y=1\)。考虑操作 \(n-(x+p)\bmod n\),画画发现可能会两两配对。

考虑它的复合:\(n-(n-(x+p)+p)=x\),竟然真的配对了。

但是显然奇数一定有孤立的。

这个时候奇偶要分开讨论。

我们考虑方程 \(n-x-p \equiv x \pmod n\) 的解。

显然模数是奇数的时候有逆元,所以有唯一一个孤立点,循环数为 \(\frac{n+1}{2}\)

当模数是偶数时,如果 \(n-p\) 是奇数,方程无解,有 \(\frac{n}{2}\) 个循环。

否则根据值域得出所有可行的 \(x\),当 \(p \leq \frac{n}{2}\),则 \(x=\frac{n+p}{2}\)\(\frac{2n+p}{2}\),否则是 \(\frac{2n+p}{2}\)\(\frac{3n+p}{2}\)

此时循环数为 \(\frac{n+2}{2}\)

用 Polya 公式,即颜色循环数次方求和除以群大小,即可。

#include <iostream>
#include <cstdio>
using namespace std;
#define LLI long long
int gcd(int a,int b){
	return b==0?a:gcd(b,a%b);
}
int fastpow(int a,int b){int res=1;
for(;b;b>>=1,a=a*a)if(b&1)res=a*res;return res;}
int main(){
	int a,b;LLI ans;
	while(scanf("%d%d",&a,&b)==2){
		if(a==0&&b==0)break;
		ans=0;
		for(int i=1;i<=b;++i)ans+=fastpow(a,gcd(i,b));
		if(b&1)ans+=1LL*b*fastpow(a,b+1>>1);
		else ans+=1LL*(a+1)*(b>>1)*fastpow(a,b>>1);
		ans/=b<<1;
		printf("%lld\n",ans);
	}
	return 0;
}
posted @ 2017-12-02 21:18  daklqw  阅读(283)  评论(0编辑  收藏  举报