题意:已知
求
先推公式……必不可少的一步
由欧拉函数的定义,
把
Gu(a,b)
G
u
(
a
,
b
)
展开,发现分子是a、b和ab的质因数,分母是a、b、a的质因数和b的质因数。而ab的质因数在a的质因数中有出现,在b的质因数中也有出现,也就是说
gcd(a,b)
g
c
d
(
a
,
b
)
这部分在分母多出现了一次。约去其他部分后可以得到:
令
a[i]=iϕ(i)
a
[
i
]
=
i
ϕ
(
i
)
,所求式
后面这部分可以用mobius函数求出……不会的话可以看看HDU 1695 题解
然后这题还卡常数……能不开long long的尽量用int,并且线性预处理出逆元就可以过了
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1000000+10;
bool check[maxn];
int prime[maxn],mu[maxn];
void Mobius(){
memset(check,false,sizeof(check));
mu[1]=1;
int tot=0;
for (int i=2;i<=1000000;i++){
if (!check[i]){
prime[tot++]=i;
mu[i]=-1;
}
for (int j=0;j<tot;j++){
if (i*prime[j]>1000000) break;
check[i*prime[j]]=true;
if (i%prime[j]==0){
mu[i*prime[j]]=0;
break;
}
else{
mu[i*prime[j]]=-mu[i];
}
}
}
}
int euler[maxn];
void getEuler(){
memset(euler,0,sizeof(euler));
euler[1]=1;
for (int i=2;i<=1000000;i++){
if (!euler[i]){
for (int j=i;j<=1000000;j+=i){
if (!euler[j]) euler[j]=j;
euler[j]=euler[j]/i*(i-1);
}
}
}
}
ll mod;
ll solve(int a,int b,ll k){
ll ans=0;
if (a>b) swap(a,b);
a/=k,b/=k;
for (int i=1;i<=a;i++){
ans+=1ll*mu[i]*(a/i)*(b/i);
ans%=mod;
}
ll tmp=0;
// for (int i=1;i<=a;i++){
// tmp+=1ll*mu[i]*(a/i)*(a/i);
// }
return ans-tmp/2;
}
ll qpow(ll x,ll n,ll mod){
ll ans=1;
while (n){
if (n&1) ans=ans*x%mod;
n>>=1;
x=x*x%mod;
}
return ans%mod;
}
int T;
int m,n;
ll inv[maxn];
ll a[maxn];
void init(){
inv[0]=inv[1]=1;
for (int i=2;i<=min(m,n);i++){
inv[i]=1ll*inv[mod%i]*(mod-mod/i)%mod;
}
for (int i=1;i<=min(m,n);i++){
a[i]=1ll*i*inv[euler[i]]%mod;
}
}
int main(){
#ifdef __APPLE__
freopen("1.in","r",stdin);
#endif
Mobius();
getEuler();
scanf("%d",&T);
while (T--){
ll ans=0;
scanf("%d %d %lld",&m,&n,&mod);
init();
for (int k=1;k<=min(m,n);k++){
ans+=1ll*a[k]*solve(m,n,k);
ans%=mod;
}
printf("%lld\n",ans%mod);
}
}