莫比乌斯反演--BZOJ1011

题目链接
题解:

∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = d ] \sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)=d] i=1nj=1m[gcd(i,j)=d]
= ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ [ g c d ( i , j ) = 1 ] =\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}[gcd(i,j)=1] =i=1dnj=1dm[gcd(i,j)=1]
= ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ ∑ d ∣ g c d ( i , j ) μ ( d ) =\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}\sum_{d\mid gcd(i,j)}\mu(d) =i=1dnj=1dmdgcd(i,j)μ(d)
= ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ ∑ d ∣ i , d ∣ j μ ( d ) =\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}\sum_{d\mid i ,d\mid j}\mu(d) =i=1dnj=1dmdi,djμ(d)
∑ d = 1 m i n { ⌊ n d ⌋ , ⌊ m d ⌋ } μ ( d ) ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ \sum_{d=1}^{min\{\lfloor\frac{n}{d}\rfloor,\lfloor\frac{m}{d}\rfloor\}}\mu(d)\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor} d=1min{dn,dm}μ(d)i=1dnj=1dm
∑ d = 1 m i n { ⌊ n d ⌋ , ⌊ m d ⌋ } μ ( d ) ⌊ n d ⌋ ⌊ m d ⌋ \sum_{d=1}^{min\{\lfloor\frac{n}{d}\rfloor,\lfloor\frac{m}{d}\rfloor\}}\mu(d)\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor d=1min{dn,dm}μ(d)dndm

对于 μ ( n ) \mu(n) μ(n)可以先预处理出其前缀和,然后分块求解。

代码实现:

#include <bits/stdc++.h>
using namespace std;
#define mes(a, val) memset(a, val, sizeof a)
#define ll long long

const int maxn = 5e4 + 100;
int p[maxn], mu[maxn];
bool v[maxn];
int m;

void sieze(int n)
{
    m = 0; mes(v, false);
    mu[1] = 1;
    for(int i = 2; i <= n; i ++){
        if(!v[i]){
            p[++ m] = i; mu[i] = -1;
        }
        for(int j = 1; j <= m && i * p[j] <= n; j ++){
            v[i * p[j]] = true;
            if(i % p[j]){
                mu[i * p[j]] = -mu[i];
            }
            else {
                mu[i * p[j]] = 0;
                break;
            }
        }
    }
    for(int i = 2; i <= n; i ++){
        mu[i] += mu[i - 1];
    }
}
ll solve(int n, int m){
    ll ans = 0;
    for(int l = 1, r; l <= min(n, m); l = r + 1){
        r = min(n / (n / l), m / (m / l));
        ans += 1ll * (mu[r] - mu[l-1]) * (n / l) * (m / l);
    }
    return ans;
}
int main()
{
    sieze(maxn-10);
    int T; scanf("%d", &T);
    while(T --){
        int n, m, d; scanf("%d %d %d", &n, &m, &d);
        ll ans = solve(n / d, m / d);
        printf("%lld\n", ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值