其他分享
首页 > 其他分享> > P2522 [HAOI2011]Problem b (莫比乌斯反演)

P2522 [HAOI2011]Problem b (莫比乌斯反演)

作者:互联网

题目大意:

题目链接
n n n个询问,给定 a , b , c , d , k a,b,c,d,k a,b,c,d,k,询问 ∑ x = a b ∑ x = c d [ g c d ( x , y ) = = k ] \sum_{x=a}^{b}\sum_{x=c}^{d}[gcd(x,y)==k] ∑x=ab​∑x=cd​[gcd(x,y)==k]

解题思路:

∑ x = a b ∑ x = c d [ g c d ( x , y ) = = k ] = ∑ x = 1 b ∑ x = 1 d [ g c d ( x , y ) = = k ] − ∑ x = 1 a − 1 ∑ x = 1 d [ g c d ( x , y ) = = k ] − ∑ x = 1 b ∑ x = 1 d − 1 [ g c d ( x , y ) = = k ] + ∑ x = 1 a − 1 ∑ x = 1 c − 1 [ g c d ( x , y ) = = k ] \sum_{x=a}^{b}\sum_{x=c}^{d}[gcd(x,y)==k]=\sum_{x=1}^{b}\sum_{x=1}^{d}[gcd(x,y)==k]-\sum_{x=1}^{a-1}\sum_{x=1}^{d}[gcd(x,y)==k]-\sum_{x=1}^{b}\sum_{x=1}^{d-1}[gcd(x,y)==k]+\sum_{x=1}^{a-1}\sum_{x=1}^{c-1}[gcd(x,y)==k] ∑x=ab​∑x=cd​[gcd(x,y)==k]=∑x=1b​∑x=1d​[gcd(x,y)==k]−∑x=1a−1​∑x=1d​[gcd(x,y)==k]−∑x=1b​∑x=1d−1​[gcd(x,y)==k]+∑x=1a−1​∑x=1c−1​[gcd(x,y)==k]

发现四个算式本质形式是一样的

所以我们只需要知道 ∑ 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=1n​∑j=1m​[gcd(i,j)==k]如何计算

∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = = k ] = ∑ i = 1 n k ∑ j = 1 m k [ g c d ( i , j ) = = 1 ] \sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)==k]=\sum_{i=1}^{\frac{n}{k}}\sum_{j=1}^{\frac{m}k}[gcd(i,j)==1] ∑i=1n​∑j=1m​[gcd(i,j)==k]=∑i=1kn​​∑j=1km​​[gcd(i,j)==1]

∑ i = 1 n k ∑ j = 1 m k [ g c d ( i , j ) = = 1 ] = ∑ i = 1 n k ∑ j = 1 m k ε ( g c d ( i , j ) ) \sum_{i=1}^{\frac{n}{k}}\sum_{j=1}^{\frac{m}k}[gcd(i,j)==1]=\sum_{i=1}^{\frac{n}{k}}\sum_{j=1}^{\frac{m}k}\varepsilon (gcd(i,j)) ∑i=1kn​​∑j=1km​​[gcd(i,j)==1]=∑i=1kn​​∑j=1km​​ε(gcd(i,j))

∑ i = 1 n k ∑ j = 1 m k ε ( g c d ( i , j ) ) = ∑ i = 1 n k ∑ j = 1 m k ∑ d ∣ g c d ( i , j ) μ ( d ) \sum_{i=1}^{\frac{n}{k}}\sum_{j=1}^{\frac{m}k}\varepsilon (gcd(i,j))=\sum_{i=1}^{\frac{n}{k}}\sum_{j=1}^{\frac{m}k}\sum_{d|gcd(i,j)} \mu(d) ∑i=1kn​​∑j=1km​​ε(gcd(i,j))=∑i=1kn​​∑j=1km​​∑d∣gcd(i,j)​μ(d)

变化求和顺序,枚举公约数

∑ i = 1 n k ∑ j = 1 m k ∑ d ∣ g c d ( i , j ) μ ( d ) = ∑ d = 1 μ ( d ) ∑ i = 1 n k [ d ∣ i ] ∑ j = 1 m k [ d ∣ j ] \sum_{i=1}^{\frac{n}{k}}\sum_{j=1}^{\frac{m}k}\sum_{d|gcd(i,j)} \mu(d)=\sum_{d=1}\mu(d)\sum_{i=1}^{\frac nk}[d|i]\sum_{j=1}^{\frac mk}[d|j] ∑i=1kn​​∑j=1km​​∑d∣gcd(i,j)​μ(d)=∑d=1​μ(d)∑i=1kn​​[d∣i]∑j=1km​​[d∣j]

因为 [ 1 , n k ] [1,\frac nk] [1,kn​]中d的倍数有 n k d \frac{n}{kd} kdn​个

∑ d = 1 μ ( d ) ∑ i = 1 n k [ d ∣ i ] ∑ j = 1 m k [ d ∣ j ] = ∑ d = 1 μ ( d ) ⌊ n k d ⌋ ⌊ m k d ⌋ \sum_{d=1}\mu(d)\sum_{i=1}^{\frac nk}[d|i]\sum_{j=1}^{\frac mk}[d|j]=\sum_{d=1}\mu(d)\left \lfloor \frac n{kd} \right \rfloor\left \lfloor \frac m{kd} \right \rfloor ∑d=1​μ(d)∑i=1kn​​[d∣i]∑j=1km​​[d∣j]=∑d=1​μ(d)⌊kdn​⌋⌊kdm​⌋

惊讶的发现这不就是数论分块的基本形式,接下来先算出 μ ( ) \mu() μ(),然后分块做即可

AC代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int T, a, b, c, d, k, cnt;
int mu[maxn], p[maxn], vis[maxn];
void init() {
    mu[1] = vis[1] = 1;
    for (int i = 2; i < maxn; i++) {
        if (!vis[i]) p[++cnt] = i, mu[i] = -1;
        for (int j = 1; j <= cnt && i * p[j] < maxn; j++) {
            vis[i * p[j]] = 1;
            if (i % p[j] == 0) {
                mu[i * p[j]] = 0;
                break;
            }
            else
                mu[i * p[j]] = -mu[i];
        }
    }
    for (int i = 1; i < maxn; i++) mu[i] += mu[i - 1];//求前缀和
}
int solve(int n, int m) {
  int res = 0;
  for (int i = 1, j; i <= std::min(n, m); i = j + 1) {
    j = min(n / (n / i), m / (m / i));//取min即可
    res += (mu[j] - mu[i - 1]) * (n / i) * (m / i);
    //数论分块标准的计算形式 i到j的和*(n/i)
  }
  return res;
}
int main() {
    init();
    cin >> T;
    while (T--) {
        cin >> a >> b >> c >> d >> k;
        cout << solve(b / k, d / k) - solve(b / k, (c - 1) / k) - solve((a - 1) / k, d / k)
        + solve((a - 1) / k, (c - 1) / k) << endl;
    }
}

标签:frac,gcd,int,sum,mu,反演,HAOI2011,P2522,1kn
来源: https://blog.csdn.net/weixin_45691711/article/details/110309792