题意:$m$种颜色$n$颗珠子,定义旋转和翻转两种置换,求不等价着色数
暴力求每个置换的循环节也许会$T?$
我们可以发现一些规律:
翻转:
$n$为奇数时每个置换有$1+\frac{n-1}{2}$个循环
$n$为偶数时穿过边的对称有$\frac{n}{2}$个循环,穿过点的有$\frac{n}{2}+1$个循环
旋转:
旋转$i$次的置换的循环个数为$gcd(n,i)$
可以这样想,从一个点开始每次走$i$步最后走到原位的最少步数$a$就是一个循环的长度
$ ai \equiv \pmod n$
$ i \mid ai,n \mid ai \rightarrow a=\frac{lcm(i,n)}{i}$
辣么$\frac{n}{a}=gcd(n,i)$就是循环个数啦
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-; c=getchar();}
while(c>=''&&c<=''){x=x*+c-''; c=getchar();}
return x*f;
}
int m,n;
inline int Pow(int a,int b){
int re=;
for(;b;b>>=,a*=a)
if(b&) re*=a;
return re;
}
inline int gcd(int a,int b){return b==?a:gcd(b,a%b);}
int main(){
freopen("in","r",stdin);
while(true){
m=read();n=read();
if(m==&&n==) break;
int ans=;
for(int i=;i<n;i++) ans+=Pow(m,gcd(n,i));
if(n&) ans+=n*Pow(m,(n+)>>);
else ans+=(n>>)*Pow(m,n>>)+(n>>)*Pow(m,(n>>)+);
ans/=n<<;
printf("%d\n",ans);
}
}