题目大意
将
n
n
n种颜色的珠子连接在一起形成一条由
n
n
n个珠子组成的圆形项链。你的工作是计算可以生产多少种不同的项链。一串项链可以不用上全部颜色的珠子。
两条项链相同,当且仅当两条项链旋转后能重合在一起,且对应珠子的颜色相同。
你需要将答案对一个给定的数字
p
p
p取模。
多组数据。
n<=1e9
思路
polya定理。
但n的范围过大,所以我们需要优化。
L
=
1
n
∑
0
<
k
<
n
n
g
c
d
(
k
,
n
)
L={1\over n}\sum_{0<k<n}n^{gcd(k,n)}
L=n1∑0<k<nngcd(k,n)
=
1
n
∑
d
∣
n
n
d
∑
0
<
k
<
n
[
g
c
d
(
k
,
n
)
=
d
]
~~~~={1\over n}\sum _{d|n} n^d\sum_{0<k<n}[gcd(k,n)=d]
=n1∑d∣nnd∑0<k<n[gcd(k,n)=d]
=
∑
d
∣
n
n
d
−
1
∑
0
<
k
<
n
[
g
c
d
(
k
/
d
,
n
/
d
)
=
1
]
~~~~=\sum _{d|n} n^{d-1}\sum_{0<k<n}[gcd(k/d,n/d)=1]
=∑d∣nnd−1∑0<k<n[gcd(k/d,n/d)=1]
=
∑
d
∣
n
n
d
−
1
∑
0
<
k
<
n
/
d
[
g
c
d
(
k
,
n
/
d
)
=
1
]
~~~~=\sum _{d|n} n^{d-1}\sum_{0<k<n/d}[gcd(k,n/d)=1]
=∑d∣nnd−1∑0<k<n/d[gcd(k,n/d)=1]
=
∑
d
∣
n
ϕ
(
n
/
d
)
n
d
−
1
~~~~=\sum _{d|n} \phi(n/d) n^{d-1}
=∑d∣nϕ(n/d)nd−1
那么就这样了
code:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
//When I wrote this code,God and I unterstood what was I doing
inline long long read()
{
long long ret,c,f=1;
while (((c=getchar())> '9'||c< '0')&&c!='-');
if (c=='-') f=-1,ret=0;
else ret=c-'0';
while ((c=getchar())>='0'&&c<='9') ret=ret*10+(c^48);
return ret*f;
}
long long n,m;
long long ksm(long long x,long long y)
{
x%=m;
long long ans=1;
while (y)
{
if (y&1) ans=ans*x%m;
x=x*x%m;
y>>=1;
}
return ans;
}
long long a[360005],tot;
bool b[360005];
void prime(long long x)
{
b[1]=1;
for (long long i=2;i<=x;i++)
{
if (b[i]) continue;
a[tot++]=i;
for (long long j=i*i;j<=x;j+=i) b[j]=1;
}
return;
}
long long phi(long long x)
{
long long ans=x;
for (long long i=0;a[i]*a[i]<=x;i++)
{
if (x%a[i]==0)
{
ans=ans-ans/a[i];
while (x%a[i]==0) x/=a[i];
}
}
if (x>1) ans=ans-ans/x;
return ans%m;
}
int main()
{
long long t=read();
prime(360000);
while (t--)
{
long long ans=0;
n=read(),m=read();
for (long long i=1;i*i<=n;i++)
{
if (i*i==n)
{
ans=(ans+ksm(n,i-1)*phi(i)%m)%m;
}
else if (n%i==0)
{
ans=(ans+ksm(n,i-1)*phi(n/i)%m)%m;
ans=(ans+ksm(n,n/i-1)*phi(i)%m)%m;
}
}
cout<<ans%m<<endl;
}
return 0;
}
//Now,only God know
//但行好事,莫问前程