P3455 [POI2007]ZAP-Queries

由莫比乌斯反演,

方便计算,改变一下枚举方式,我们枚举 ,则

可以看出莫比乌斯反演的实质:容斥原理

代入,

然后用整除分块即可。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define ll long long int
#define rep(i,a,b) for(int i = (a); i <= (b); i ++)
#define dwn(i,a,b) for(int i = (a); i >= (b); i --)
using namespace std;
const int maxn = 50000 + 100;

ll mu[maxn];
int cur, p[maxn], isp[maxn];
void shai()
{
    mu[1] = 1;
    rep(i,2, 50000)
    {
        if(!isp[i])
        {
            p[ ++ cur] = i;
            mu[i] = -1LL;
        }
        for(int j = 1; j <= cur && i * p[j] <= 50000; j ++)
        {
            isp[i * p[j]] = 1;
            if(i % p[j] == 0)
            {
                mu[i * p[j]] = 0;
                break;
            }
            else
            {
                mu[i * p[j]] = mu[i] * mu[p[j]];
            }
        }
    }
    rep(i, 2, 50000)
        mu[i] = mu[i - 1] + mu[i];
}
int main()
{
    shai();
    int T;
    cin >> T;
    rep(i, 1, T)
    {
        ll a, b, d;
        cin >> a >> b >> d;
        ll N = min(a, b) / d;
        ll Ans = 0;
        a /= d;
        b /= d;
        for(ll l = 1LL,r;l <= N; l = r + 1)
        {
            r = min(a / (a / l), b / (b / l));
            Ans += (mu[r] - mu[l - 1]) * (a / l) * (b / l);
        }
        cout << Ans << endl;
    }
    return 0;
}