D17 T3 summer simple questions 2 (Mobius inversion)

Title Description

Jia one hundred glass just learning the Mobius inversion, wanted to do a simple question practice your hand.
Provided $ \ sigma _ {0} \ left (x \ right) $ $ X is the number of submultiple $ given $ N $ and $ M $, seeking:
$ \ sum_ {I} = ^ {N}. 1 \ sum_ {j = 1} ^ {M} \ sigma _ {0} \ left (ij \ right) $
to 100% of the data, $ T \ leq 50000,1 \ leq N, M \ leq50000 $

answer

First there is a nature $ \ sigma _ {0} \ left (ij \ right) = \ sum_ {x | i} \ sum_ {y | j} \ left [gcd \ left (x, y \ right) = 1 \ right ] $
the answer is $ \ sum_ {i = 1} ^ {N} \ sum_ {j = 1} ^ {M} \ sum_ {x | i} \ sum_ {y | j} \ left [gcd \ left (x , y \ right) = 1 \ right] $
to enumerate $ x, y $, $ \ sum_ {i = 1} ^ {N} \ sum_ {j = 1} ^ {M} \ left [gcd \ left ( i, j \ right) = 1 \ right] \ left \ lfloor \ frac {N} {i} \ right \ rfloor \ left \ lfloor \ frac {M} {j} \ right \ rfloor $
further inversion, $ \ sum_ {d = 1} ^ {min (n, m)} \ mu (d) \ sum_ {i = 1} ^ {\ frac {N} {d}} \ left \ lfloor \ frac {N} {di } \ right \ rfloor \ sum_ { j = 1} ^ {\ frac {M} {d}} \ left \ lfloor \ frac {M} {dj} \ right \ rfloor $
credited $ f (i) = \ sum_ { j = 1} ^ {i} \ left \ lfloor \ frac {i} {j} \ right \ rfloor $
we claim is $ \ sum_ {i = 1} ^ {min (n, m)} \ mu (i ) * f (\ left \ lfloor \ frac {N} {i} \ right \ rfloor) * f (\ left \ lfloor \ frac {M} {i} \ right \ rfloor) $
pretreatment $ f $ array on ok , in fact, $ f (n) $ array is $ [1, n] $ divisor and, as can be seen enumerate about the number $ j $.

#include<bits/stdc++.h>
using namespace std;

#define ll long long
const int maxn=50006;
int t,n,m;
int cnt,prime[maxn],mu[maxn];
ll f[maxn],ans[6006][6006];
bool not_prime[maxn];

void init(){
    mu[1]=1;
    for(int i=2;i<=50000;i++){
        if(!not_prime[i]){
            prime[++cnt]=i;
            mu[i]=-1;
        }
        for(int j=1;prime[j]*i<=50000;j++){
            not_prime[i*prime[j]]=true;
            if(i%prime[j]) mu[i*prime[j]]=-mu[i];
            else {
                mu[i*prime[j]]=0;
                break;
            }
        }
        mu[i]+=mu[i-1];
    }
    for(int i=1;i<=50000;++i) 
     for(ll l=1,r;l<=i;l=r+1){
        r=i/(i/l);
        f[i]+=(r-l+1)*(i/l);
    }
}

int main(){
    freopen("c.in","r",stdin);
    freopen("c.out","w",stdout);
    init();
    scanf("%d",&t);
    while(t--){
        ll ret=0;
        scanf("%d%d",&n,&m);
        if(n>m) swap(n,m);
        if(n<=6000&&m<=6000&&ans[n][m]){
            printf("%lld\n",ans[n][m]);
            continue;
        }
        for(int l=1,r;l<=n;l=r+1){
            r=min(n/(n/l),m/(m/l));
            ret+=(mu[r]-mu[l-1])*f[n/l]*f[m/l];
        }
        if(n<=6000&&m<=6000) ans[n][m]=ans[m][n]=ret;
        printf("%lld\n",ret);
    }
}
View Code

 

Guess you like

Origin www.cnblogs.com/sto324/p/11272867.html