[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;
}