题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6390
Gu(a,b)=ϕ(ab)/ϕ(a)ϕ(b)
现在求a从1到n,b从1到m的Gu(a,b)的总和
由欧拉函数的表达式,n可分解为p1^a1*p2^a2*...pn^an
则φ(n)=∏(pi-1)(pi^(ai-1))
将a和b分解质因数,设a和b都有质因数p,a中一项为p^a1,b中一项为p^a2,则
当a1=0时,原式中此项为1,。所以只有ab同时含有p这个质因数时,才会对答案有所贡献。
在最后的式子中,对于每个分子中的p和分母中的(p-1)都将他们加上对应a1、a2的最小值的次幂,原式就变成了:
(a,b)/φ((a,b))
之后就是容斥
f【i】代表gcd为i的倍数的ab对数
g【i】代表gcd为i的ab对数
从后向前O(n)遍历f【i】=(n/i)*(m/i);
g【i】=f【i】-f【i*2】-f【i*3】。。。。
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define For(i,m,n) for(int i=m;i<=n;i++)
#define Dor(i,m,n) for(int i=m;i>=n;i--)
#define LL long long
#define lan(a,b) memset(a,b,sizeof(a))
using namespace std;
const LL N=1000000;
int pr[N/5],p[N+100],tot,phi[N+100];
LL f[N+10],inv[N+10];
int n,m,mod;
void init()
{
phi[1]=1;p[1]=1;
For(i,2,N){
if(!p[i])p[i]=i,pr[++tot]=i,phi[i]=p[i]-1;
for(int j=1;j<=tot&&pr[j]*i<=N;j++){
p[i*pr[j]]=pr[j];
if(p[i]==pr[j]){
phi[i*pr[j]]=phi[i]*pr[j];
break;
}else phi[i*pr[j]]=phi[i]*(pr[j]-1);
}
}
}
int main()
{
init();
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&mod);
n=min(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]=(LL)(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;
}
printf("%lld\n",ans);
}
return 0;
}