求长度为 \\(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;
}