给一个n个点的环染m种颜色,有3种操作,分别为旋转、翻转和把所有颜色编号+1
如果两个方案在经过任意次操作之后等价了这两个方案就是等价的
求所有本质不同的染色方案数
n,m<=1e18,保证n,m逆元存在
burnside裸题,但是多了一个颜色操作
把颜色操作也视为置换,考虑他对经典的两种置换的影响
对于旋转,我们每一组的循环节长度为n/(i,n)
如果它在+把所有颜色d(0<=d< m)后能变回它自己它就是一个不动点
那么循环节种的每一个元素在模m意义下都比上一个元素大d
能变回原样就是n/(i,n)d≡ 0 mod m
经过一些简单的数论推导我们可以得出d有(m,n/(i,n))种取值
于是我们的旋转就变成了
#include
#include
#include
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int Mo=998244353,S=3;
ll mult(ll x,ll y,ll Mo) {
x%=Mo;y%=Mo;
ll tmp=(ll)((long double)x*y/Mo+1e-8)*Mo;
return (x*y-tmp+Mo)%Mo;
}
ll pwr(ll x,ll y,ll Mo) {
ll z=1;x%=Mo;y%=(Mo-1);
for(;y;y>>=1,x=mult(x,x,Mo))
if (y&1) z=mult(z,x,Mo);
return z;
}
ll gcd(ll x,ll y) {
if (!x) return 1;
if (x<0) return gcd(-x,y);
return y?gcd(y,x%y):x;
}
ll n,m,ans,nn,mm,invm;
ll pri[70],a[20];
int tot,cnt,b[20],tmp;
bool check(ll a,ll n,ll x,ll t) {
ll res=pwr(a,x,n),lst=res;
fo(i,1,t) {
res=mult(res,res,n);
if (res==1&&lst!=1&&lst!=n-1) return 1;
lst=res;
}
if (res!=1) return 1;
else return 0;
}
bool Miller_Rabin(ll n) {
if (n<2) return 0;
if (n==2) return 1;
if (!(n&1)) return 0;
ll x=n-1,t=0;
while (!(x&1)) x>>=1,t++;
fo(i,1,S) {
ll a=rand()%(n-1)+1;
if (check(a,n,x,t)) return 0;
}
return 1;
}
ll Pollard_rho(ll n,ll t) {
int i=1,k=2;
ll x0=rand()%n,y=x0;
while (1) {
i++;
x0=(mult(x0,x0,n)+t)%n;
ll d=gcd(y-x0,n);
if(d!=1&&d!=n) return d;
if(y==x0) return n;
if(i==k) y=x0,k<<=1;
tmp++;
}
}
void find(ll n) {
if (n==1) return;
if (Miller_Rabin(n)) {
pri[++tot]=n;
return;
}
ll p=n;tmp=0;
while (p>=n) p=Pollard_rho(p,rand()%(n-1)+1);
printf("%d\n",tmp);
find(p);find(n/p);
}
void dfs(int x,ll y,ll phi) {
if (x>cnt) {
(ans+=gcd(y,m)%Mo*pwr(m,n/y,Mo)%Mo*phi%Mo)%=Mo;
return;
}
ll z=1,p=1;
fo(i,0,b[x]) {
dfs(x+1,y*z,phi*p%Mo);
z=z*a[x];
if (i==0) p=p*(a[x]-1)%Mo;
else p=p*a[x]%Mo;
}
}
int ty;
int main() {
freopen("necklace.in","r",stdin);
freopen("necklace.out","w",stdout);
ll inv2=pwr(2,Mo-2,Mo);srand(233333);
for(scanf("%d",&ty);ty;ty--) {
scanf("%lld%lld",&n,&m);
nn=n%Mo;mm=m%Mo;
if (n&1) ans=pwr(m,n/2+1,Mo)*nn%Mo;
else {
if (m&1) ans=pwr(m,n/2,Mo)*nn%Mo*inv2%Mo;
else ans=pwr(m,n/2,Mo)*nn%Mo;
(ans+=pwr(m,n/2+1,Mo)*nn%Mo*inv2%Mo)%=Mo;
}
tot=cnt=0;find(n);
sort(pri+1,pri+tot+1);
fo(i,1,tot)
if (pri[i]!=pri[i-1]) a[++cnt]=pri[i],b[cnt]=1;
else b[cnt]++;
dfs(1,1,1);
ans=ans*pwr(nn*mm*2%Mo,Mo-2,Mo)%Mo;
printf("%d\n",ans);
}
}