打个表不难发现
fm(i)=m((i,p−1)−1)
f
m
(
i
)
=
m
(
(
i
,
p
−
1
)
−
1
)
,然后随便反演一下即可。
证明略。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<assert.h>
#include<unordered_map>
#define mod 1000000007
#define lint long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int fast_pow(int x,int k,int p,int ans=1)
{ for(x%=p;k;k>>=1,x=(lint)x*x%p) (k&1)?ans=(lint)ans*x%p:0;return ans; }
inline int gcd(int a,int b) { return a?gcd(b%a,a):b; }
unordered_map<int,int> PHI;
int lst[100],lt;
inline int getlst(int n)
{
int x=1;
while((x+1ll)*(x+1)<=n) x++;
rep(i,2,x) if(n%i==0)
{ lst[++lt]=i;while(n%i==0) n/=i; }
if(n>1) lst[++lt]=n;return 0;
}
inline int Phi(int n)
{
if(n==1) return 1;if(PHI.count(n)) return PHI[n];
for(int i=1;i<=lt;i++) if(n%lst[i]==0)
{
int x=n/lst[i];
if(x%lst[i]==0) PHI[n]=Phi(x)*lst[i];
else PHI[n]=Phi(x)*(lst[i]-1);
}
return PHI[n];
/*int x=1,ans=n;
while((x+1ll)*(x+1)<=n) x++;
rep(i,2,x) 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 main()
{
int m,p;scanf("%d%d",&m,&p),getlst(p-1);
/* rep(i,1,p-1)
{
int cnt=0;
rep(x,1,p-1) rep(y,1,m) if(fast_pow(x+1,i,p)==fast_pow(x,i,p)) cnt++;
cout<<i<<" "<<cnt<<endl;
assert(cnt==m*(gcd(p-1,i)-1));
}*/
//conclusion : f_m(i)=m(gcd(i,p-1)-1)
int n=p-1;lint ans=0ll;
rep(d,1,n/d) if(n%d==0)
{
(ans+=(d-1ll)*Phi(n/d)%mod)%=mod;
if(d!=n/d) (ans+=(n/d-1ll)*Phi(d)%mod)%=mod;
}
ans=ans%mod*n%mod;
ans=(ans+n*(n-1ll)%mod)%mod;
ans=ans%mod*fast_pow(2,mod-2,mod)%mod;
ans=ans*m%mod;
return !printf("%lld\n",ans);
}