题意:

。给定m,n,p,求。其中,p为质数。

思路:

可以推导出

举个例子形象一点,

因为有欧拉公式,其中x,y为n的质因子。

化简后分母只剩下的质因子的部分,上下同乘,得

这里分子就是,分母则是中减去2的倍数的个数,减去3的倍数的个数,加上6的倍数的个数,这个容斥就是求出了比小的数中与它互质的数的个数,即

所以问题就转化为了求。这里用到了容斥。

枚举。设f[i]:gcd为i的倍数的(a,b)对数,g[i]:gcd为i的(a,b)对数。

以a=6,b=8为例,

所以就可以求出g[i]了。

代码:

#define MAXN 1000000
typedef long long ll;
ll eu[MAXN+10];
ll pri[MAXN+10];
bool vis[MAXN+10];
ll f[MAXN+10];//gcd为i的倍数的对数
ll g[MAXN+10];//gcd为i的对数
ll inv[MAXN+10];
void init()
{
    eu[1]=1;
    ll cnt=0;
    for(ll i=2;i<=MAXN;i++)
    {
        if(!vis[i]){pri[cnt++]=i;eu[i]=i-1;}
        for(int j=0;j<=cnt&&pri[j]*i<=MAXN;j++)
        {
            vis[i*pri[j]]=1;
            if(i%pri[j]==0)
            {
                eu[i*pri[j]]=eu[i]*pri[j];
                break;
            }
            eu[i*pri[j]]=eu[i]*(pri[j]-1);
        }
    }
}
long long PowerMod(ll a,ll b,ll c)
{
    long long ans=1;
    long long k;
    k=a;
    while(b>0)
    {
        if(b%2==1)
        ans=(ans*k)%c;
        b=b/2;
        k=(k*k)%c;
    }
    return ans;
}
int main()
{
    int t;
    ll m,n,p;
    init();
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld%lld",&m,&n,&p);
        ll ans=0;
        for(ll i=1;i<=min(m,n);i++)
            f[i]=(m/i)*(n/i);
        ll tot=min(m,n);
        inv[1]=1;
        for(ll i=2;i<=tot;i++)
           inv[i]=(p-(p/i))*inv[p%i]%p;
        for(ll i=tot;i>=1;i--)
        {
            g[i]=f[i];
            for(ll j=2;i*j<=tot;j++)
                g[i]=(g[i]-g[i*j]+p)%p;
            ll temp=g[i];
            temp=((temp*i)%p*inv[eu[i]])%p;
            ans=(ans+temp)%p;
        }
        printf("%lld\n",ans);
    }
    return 0;
}