Input
Input contains an integer T indicating the number of cases, followed by T lines. Each line contains three integers m,n,p as described above.
1≤T≤3
1≤m,n≤1,000,000
max(m,n)<p≤1,000,000,007
And given p is a prime.
Output
Please output exactly T lines and each line contains only one integer representing the answer.
Sample Input
1
5 7 23
Sample Output
2
题意:利用欧拉函数定义了一个Gu(x,y)函数,求图中的和公式。
思路:先奉上官方题解
关于上面欧拉函数的变换,直播中简单证了一下设a和b有公因子素数p,其中a=p^a1,b=p^a2,(假设a1>a2)然后根据图中公式展开欧拉函数并利用欧拉函数是积性函数的性质得图中结论。
经过公式的变换得到既可以用莫比乌斯反演做,然后直播中又讲了一个好方法。
设 F[d]表示d|gcd(a,b)的个数
f[d]=d=gcd(a,b)的个数
F[d]=(n/d)*(m/d);
f[d]=F[d]-sum( f[i*d] | i>=2)。
代码:
#define size 1000001
ll m,n,mod;
ll phi[size];
ll inv[1000005],f[1000005];
void getphi()
{
memset(phi,0,sizeof(phi));
phi[1]=1;
for(int i=2;i<size;i++)
{
if(!phi[i])
{
for(int j=i;j<size;j+=i)
{
if(!phi[j]) phi[j]=j;
phi[j]=phi[j]/i*(i-1);
}
}
}
}
int main()
{
int T_T;
getphi();
scanf("%d",&T_T);
while(T_T--)
{
scanf("%lld%lld%lld",&m,&n,&mod);
if(n>m) swap(n,m);
inv[1]=1;
for (int i=2;i<=n;i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
ll ans=0;
for(int i=n;i>=1;i--)
{
f[i]=(n/i)*(m/i);
for(int j=i+i;j<=n;j+=i)
{
f[i]=f[i]-f[j];
}
ans=(ans+((f[i]%mod*i)%mod)*inv[phi[i]]%mod)%mod;
}
cout<<ans<<endl;
}
}