[BZOJ 2301] [HAOI 2011] Problem b (Mobius inversion) (with proof)

[BZOJ 2301] [HAOI 2011] Problem b (Mobius inversion) (with proof)

Face questions

T group query, each given a, b, c, d, k, find \ (\ sum _ {i = a} ^ b \ sum _ {j = c} ^ d [gcd (i, j) = k ] \)

\(T,a,b,c,d,k\le 5\times 10^4\)

analysis

\ (O (n ^ 2) \) violence is obviously not feasible, we consider optimization.

First easy to get \ (k \ Times gcd (i, J) = gcd (ki, kJ) \) , then we can put a, b, c, d are in addition to the k, the question becomes \ (\ sum _ {i = a / k} ^ {b / k} \ sum _ {j = c / k} ^ {d / k} [gcd (i, j) = 1] \) division (described later if not, are to go on the whole)

What difference, as long as we obtain \ (\ sum_. 1} ^ {n-I = \ sum_. 1} = {J ^ m [GCD (I, J) =. 1] \) , then the prefix and subtraction of two-dimensional look can the

1. The use of Dirichlet convolution prove

The following is the preliminary knowledge, master can skip

definition:

Unit function \ (\ varepsilon \ left (I \ right) = \ left [= I. 1 \ right] \) ,

Normal function \ (I (i) = 1 \)

狄利克雷卷积\(\left(g\ast f\right)\left(i\right)=F\)表示\(F\left(i\right)=\sum_{d|i}g\left(d\right)f\left(\frac id\right)\)

Then we have the following conclusions \ (\ left (\ MU \ AST the I \ right) = \ varepsilon \) , i.e., \ (\ varepsilon (n-) = \ D SUM _ {|} n-\ MU (n-) \) .

prove:

\ (n = 1 \) is clearly established when

\ (n> 1 \) , the set of n prime factorization of \ (\ sum_ {I =. 1} ^ {T} P_i ^ {K_i} \) , D is in the inside select some cases prime factors multiplied together. Only the election of the prime factors of the index 1 when the answer will have to contribute 1 or -1, depending. The question then is converted into the number of program number 0,1,2,3 ... t selected number. The answer is \ (C_ {t} ^ 0 -C_ {t} ^ 1 + C_ {t} ^ 2-C_ {t} ^ 3 \ dots = \ sum_ {i = 1} ^ t (-1) ^ {i -1} C_ {t} ^ i = \ sum_ {i = 0} ^ {t} (1) ^ {ti} (- 1) ^ i C_ {t} ^ i = (1-1) ^ t = 0 \) . penultimate step to use the binomial theorem. Therefore $ \ sum _ {d | n } \ mu (n) = 0 = \ varepsilon (n) $

The conclusions \ (\ left (\ MU \ AST the I \ right) = \ varepsilon \) , i.e., \ (\ varepsilon (n-) = \ SUM _ {D | n-} \ MU (n-) \) , we can simplify problem formula

Defined by the known \ (\ epsilon (x) = [x = 1] \)

\[\sum_{i=1}^n \sum_{j=1}^m [gcd(i,j)=1]=\sum_{i=1}^n \sum_{j=1}^m \varepsilon(gcd(i,j))=\sum_{i=1}^n \sum_{j=1}^m \sum_{d|gcd(i,j)} \mu(d)\]

Transform summation order, first enumeration \ (d | gcd (i, J) \) ,

\[\sum_{d=1}^n \mu(d) \sum_{i=1}^n [d|i] \sum_{j=1}^m [d|j]\],

Where \ ([d | i] \) expressed as a multiple of d i when i will contribute to answer

There is clearly a multiple of d n / d 1 ~ n in number

The final answer is \ [\ sum_ {d = 1 } ^ {min (n, m)} \ mu (d) \ lfloor \ frac {n} {d} \ rfloor \ lfloor \ frac {m} {d} \ rfloor \]

2. The use of Mobius inversion of the second form of proof

The second form is the Mobius inversion

If \ (F. (N-) = \ SUM _ {n-| D} F (D) \) , then the \ (f (n) = \ sum_ {n | d} \ mu (d) F (\ lfloor \ frac { d} {n} \ rfloor) \)

Where d represents a multiple of n

Now use the Mobius inversion, we must first find the right F and f

Assume

\ (F (x) = \ sum_ {I} ^ x [gcd (x, I) = I] \) (x is the number of gcd (x, Y)), and

\ (F. (X) = \ sum_ {I} [x | GCD (x, I)] \) , (GCD is a multiple of the number of x or x (x, y)) of

Although this appears to be infinite summation, we actually seek to min (n, m) can be, because gcd (i, j) (i <n, j <m) can not exceed i, j is the smallest value.

Apparently $ F (x) = \ sum f (i) $ (i is a multiple of x), because gcd (x, i) can be divisible by x, then i will be able divisible by x.

Since F, f satisfy the above conditions, we will be a strong inversion

\[f(x)= \sum_{x|d} \mu(d) F(\lfloor \frac{d}{x} \rfloor)\]

Noting \ (F (x) = \ sum_ {i} [x | gcd (x, i)] = \ lfloor \ frac {n} {x} \ rfloor \ lfloor \ frac {m} {x} \ rfloor \ ) , since the GCD (i, j) is a multiple of x, then i, j are divisible x must, obviously a multiple of n 1 to n, x has a / x a

We find the answer in fact is f (1)

\[f(1)= \sum_{1|d} \mu(d) F(\lfloor \frac{d}{1} \rfloor)= \sum_{d=1}^{min(n,m)} \mu(d) F(d)= \sum_{d=1}^{min(n,m)} \mu(d) \lfloor \frac{n}{d} \rfloor \lfloor \frac{m}{d} \rfloor\]

Both methods the same thing, are obtained the final answer \ [\ sum_ {d = 1 } ^ {min (n, m)} \ mu (d) \ lfloor \ frac {n} {d} \ rfloor \ lfloor \ frac {m} {d} \ rfloor \]

Number Theory block optimization

Enumeration solving violent \ [\ sum_ {d = 1 } ^ n \ mu (d) \ lfloor \ frac {n} {d} \ rfloor \ lfloor \ frac {m} {d} \ rfloor \] complexity is \ (O (n-) \) , is still high, was observed when large d n / d of little value change, such as when n = 6 n / 4 = n / 5 = n / 6.

Thus we can find the same value for all the rounding interval [l, r], then $ \ lfloor \ frac {n} {l} \ rfloor \ sum_ {i = l} ^ r \ mu (d) $ to The answer can be obtained, summing section may prefix and pretreatment. For one block, assuming its starting position index is L, it can be obtained that the end position of its index of n / (n / l)

Such complexity is \ (O (\ sqrt n) \) a, T is the time complexity of the query \ (O (T \ sqrt n-) \) , this problem can be

long long ans=0;
int l,r;
for(l=1;l<=m;l=r+1){
    r=min(n/(n/l),m/(m/l));
    ans+=(sum_mu[r]-sum_mu[l-1])*(n/l)*(m/l);
}

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 50000
using namespace std;
typedef long long ll;
int cnt;
bool vis[maxn+5];
int prime[maxn+5];
int mu[maxn+5];
ll sum_mu[maxn+5];
void sieve(int n){
    mu[1]=1;
    for(int i=2;i<=n;i++){
        if(!vis[i]){
            prime[++cnt]=i;
            mu[i]=-1;
        }
        for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
            vis[i*prime[j]]=1;
            if(i%prime[j]==0){
                mu[i*prime[j]]=0;
                break;
            }else mu[i*prime[j]]=-mu[i];
        }
    }
    for(int i=1;i<=n;i++) sum_mu[i]=sum_mu[i-1]+mu[i];
}

int t;
int a,b,c,d,e;
ll solve(int n,int m){
    n/=e;
    m/=e;
    if(n<m) swap(n,m);
    ll ans=0;
    int l,r;
    for(l=1;l<=m;l=r+1){
        r=min(n/(n/l),m/(m/l));
        ans+=(sum_mu[r]-sum_mu[l-1])*(n/l)*(m/l);
    }
    return ans;
}

int main(){
    sieve(maxn);
    scanf("%d",&t);
    while(t--){
        scanf("%d %d %d %d %d",&a,&b,&c,&d,&e);
        ll ans=solve(b,d)-solve(a-1,d)-solve(b,c-1)+solve(a-1,c-1);
        printf("%lld\n",ans);
    }
}

Guess you like

Origin www.cnblogs.com/birchtree/p/11355045.html