这题如果变量全用long long 会超时。。。。
已知珠子的颜色和个数都为n,只考虑旋转,不考虑翻转,问能形成多少种项链。
因为n很大,不能直接枚举i,计算 gcd(n,i)
但是可以换一个思路 gcd(n,i)=w ,w为循环节的个数,那么n/w则为单个循环节的长度 l(每个循环节的长度都相等,因为项链旋转后,原来相邻的珠子现在还相邻,所以在计算循环时,每个循环的长度相等) 那么gcd(n/w,i/w)=w/w=1,所以要计算有多少个i使gcd(n,i)=w,就可以通过计算 有多少个gcd(n/w,i/w)=gcd(l,i/w)=1来得到,也就是有多少个比l小且和l互素数,也就是euler(l)
枚举w,只需到w*w<=n即可,因为如果存在长度w,那么也就存在长度n\w(w,和n\w为n的因子),计算时euler(i)*poww(n,n/i-1) -1是因为最后除|g| |g|==n,
#include<iostream>
using namespace std;
int mod;
int eulr(int n)
{
int ans=n;
for(int i=2;i*i<=n;i++)
{
if(n%i==0)
{
ans=ans/i*(i-1);
while(n%i==0) n/=i;
}
}
if(n!=1) ans=ans/n*(n-1);
return ans;
}
int poww(int a,int b)
{
int ans=1;
a=a%mod;
for(;b;a=a*a%mod,b=b>>1)
{
if(b&1)
ans=ans*a%mod;
}
return ans;
}
int main()
{
std::ios::sync_with_stdio(false);
int x,n;
cin>>x;
while(x--)
{
cin>>n>>mod;
long long ans=0;
for(int i=1;i*i<=n;i++)
{
if(n%i==0)
{
if(i*i==n) ans+=eulr(i)%mod*poww(n,i-1)%mod;
else
{
ans+=eulr(i)%mod*poww(n,n/i-1)%mod+eulr(n/i)%mod*poww(n,i-1)%mod;
}
ans=ans%mod;
}
}
cout<<ans<<endl;
}
}