莫比乌斯反演入门(一)--P2522

前置知识:

1.数论分块,二维数论分块

2. ⌊ a b c ⌋ = ⌊ ⌊ a b ⌋ c ⌋ \lfloor\frac{a}{bc}\rfloor = \lfloor\frac{\lfloor\frac{a}{b}\rfloor}{c}\rfloor bca=cba

3. g c d ( i , j ) = k → g c d ( i k , j k ) = 1 gcd(i,j)=k \to gcd(\frac ik,\frac jk)=1 gcd(i,j)=kgcd(ki,kj)=1

OI WIKI 上面莫比乌斯反演前置知识

题目大意:

地址

∑ i = a b ∑ j = c d [ g c d ( i , j ) = = k ] \sum_{i=a}^{b}\sum_{j=c}^{d}[gcd(i,j)==k] i=abj=cd[gcd(i,j)==k]

所 有 变 量 ≤ 5 e 4 所有变量 \leq 5e4 5e4

题目思路:

莫比乌斯反演主要就是公式推导。

这个二维区间函数和容斥一下变成求 ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = = k ] \sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)==k] i=1nj=1m[gcd(i,j)==k]

原式 = ∑ i = 1 n ∑ j = 1 m [ g c d ( i k , j k ) = = 1 ] =\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(\frac ik,\frac jk)==1] =i=1nj=1m[gcd(ki,kj)==1]

= ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ m k ⌋ [ g c d ( i , j ) = = 1 ] =\sum_{i=1}^{\lfloor \frac nk\rfloor}\sum_{j=1}^{\lfloor \frac mk\rfloor}[gcd(i,j)==1] =i=1knj=1km[gcd(i,j)==1]

= ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ m k ⌋ ∑ d ∣ g c d ( i , j ) μ ( d ) =\sum_{i=1}^{\lfloor \frac nk\rfloor}\sum_{j=1}^{\lfloor \frac mk\rfloor}\sum_{d|gcd(i,j)}^{}\mu( d) =i=1knj=1kmdgcd(i,j)μ(d)

接下来变换求和顺序。按约数来计算 μ \mu μ的和

= ∑ d = 1 m i n ( ⌊ n k ⌋ , ⌊ m k ⌋ ) μ ( d ) ∑ d ∣ i ⌊ n k ⌋ ∑ d ∣ j ⌊ m k ⌋ =\sum _{d=1} ^{min(\lfloor \frac nk\rfloor, \lfloor \frac mk\rfloor)} \mu(d) \sum _{d|i} ^{\lfloor \frac nk\rfloor} \sum _{d|j} ^{\lfloor \frac mk\rfloor} =d=1min(kn,km)μ(d)dikndjkm

显然, [ 1 , ⌊ n k ⌋ ] [1,\lfloor \frac{n}{k} \rfloor] [1,kn]内有 ⌊ ⌊ n k ⌋ d ⌋ \lfloor\frac{\lfloor\frac{n}{k}\rfloor}{d}\rfloor dkn d d d的倍数

= ∑ d = 1 m i n ( ⌊ n k ⌋ , ⌊ m k ⌋ ) μ ( d ) ⌊ ⌊ n k ⌋ d ⌋ ⌊ ⌊ m k ⌋ d ⌋ =\sum _{d=1} ^{min(\lfloor \frac nk\rfloor, \lfloor \frac mk\rfloor)} \mu(d) \lfloor\frac{\lfloor\frac{n}{k}\rfloor}{d}\rfloor \lfloor\frac{\lfloor\frac{m}{k}\rfloor}{d}\rfloor =d=1min(kn,km)μ(d)dkndkm

线性筛筛出莫比乌斯函数,然后二维数论分块即可。

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define vi vector<int>
#define vll vector<ll>
#define fi first
#define se second
const int maxn = 5e4 + 5;
const int mod = 1e9 + 7;
int a[maxn];
int u[maxn] , bk[maxn] , p[maxn] , cnt;
void init ()
{
    u[1] = 1;
    for (int i = 2 ; i < maxn ; i++){
        if (!bk[i]){
            p[++cnt] = i;
            u[i] = -1;
        }
        for (int j = 1 ; j <= cnt && i * p[j] < maxn ; j++){
            bk[i * p[j]] = 1;
            if (i % p[j] == 0) {
                u[i * p[j]] = 0;
                break;
            }else {
                u[i * p[j]] = -u[i];
            }
        }
    }
    for (int i = 1 ; i < maxn ; i++) u[i] += u[i - 1];
    return ;
}
ll solve (ll n , ll m)
{
    ll ans = 0;
    for (ll l = 1 , r ; l <= min(n , m) ; l = r + 1){
        r = min(n / (n / l) , m / (m / l));
        ans += (u[r] - u[l - 1]) * (n / l) * (m / l);
    }
    return ans;
}
int main()
{
    ios::sync_with_stdio(false);
    init();
    int t; cin >> t;
    while (t--){
        ll a , b , c , d , k;
        cin >> a >> b >> c >> d >> k;
        // (a , c) (b , d)
        ll ans = solve(b / k , d / k) - solve((a - 1) / k , d / k)
                - solve(b / k , (c - 1) / k) + solve((a - 1) / k , (c - 1) / k);
        cout << ans << endl;
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值