这个题目和莫比乌斯反演并没有太大关系,只是用了莫比乌斯函数而已,本质就是整数分块+容斥原理.
题目很简单:对于给定的整数a,b和d,有多少正整数对x,y,满足x<=a,y<=b,并且gcd(x,y)=d.
这个怎么做呢?我们转化一下,就变成了x'=a/d,y'=b/d.并且gcd(x',y')=1的个数.这个O(n)的做法大家都会吧,但是数据自带5e5的查询,显然NT是过不去的,先讲讲nt做法,就是总数为x'*y'.x'中含有因子2的有x'/2个,同理y'中含有因子2的有y'/2.到了3也是一样的,然后我们会发现这两个的最小公倍数计算了2次,就要减去.以此容斥下去.会发现就是莫比乌斯函数,所以我们可以用线性筛求莫比乌斯函数,然后就是一个公式.
图片说明
答案就是这个qaq.
然后我们来思考怎么优化这个算法.然后就是个经典的整数分块了.不懂的看视频.hhh.我做的.
https://www.bilibili.com/video/BV19i4y1s7nH
预处理下mubius函数数组,然后前缀以下就好了.
代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+5;
int sum[N],mob[N];
int st[N],prime[N];
void mobius()
{
    mob[1]=1;int g=0;
    for(int i=2;i<=N-5;i++)
    {
        if(!st[i])  {prime[g++]=i;mob[i]=-1;}
        for(int j=0;prime[j]*i<=(N-5);j++)
        {
            st[prime[j]*i]=1;
            if(i%prime[j]==0)   {mob[prime[j]*i]=0;   break;}
            mob[prime[j]*i]=(-1)*mob[i];
        }
    }
    for(int i=1;i<=N-5;i++)
    {
        sum[i]+=sum[i-1]+mob[i];
    }
}//处理mobius数组和前缀数组

int main()
{
    int T,a,b,d;
    cin>>T;
    mobius();
    while(T--)
    {
        cin>>a>>b>>d;
        //整数分块.
        ll ans=0;
        int x=a/d,y=b/d;
        for(int l=1,r;l<=min(x,y);l=r+1)
        {
            r=min(min(x/(x/l),y/(y/l)),min(x,y));
            ans+=(sum[r]-sum[l-1])*1ll*(x/l)*(y/l);
        }
        cout<<ans<<endl;
    }
    return 0;
}