模板 - 莫比乌斯反演

Posted yinku

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板 - 莫比乌斯反演相关的知识,希望对你有一定的参考价值。

P3455 [POI2007]ZAP-Queries https://www.luogu.org/problemnew/show/P3455

最简单的求gcd==d的个数,直接分块瞎搞。

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

#define MAXN 50000
int mu[MAXN+5];

int pri[MAXN+5],pritop;
bool notpri[MAXN+5];
//pritop从1开始计数

int summu[MAXN+5];

void sieve3(int n) {
    notpri[1]=mu[1]=1;
    for(int i=2; i<=n; i++) {
        if(!notpri[i])
            pri[++pritop]=i,mu[i]=-1;
        for(int j=1; j<=pritop&&i*pri[j]<=n; j++) {
            notpri[i*pri[j]]=1;
            //略有不同
            if(i%pri[j])
                mu[i*pri[j]]=-mu[i];
            else {
                mu[i*pri[j]]=0;
                break;
            }
        }
    }

    for(int i=1;i<=n;i++){
        summu[i]=summu[i-1]+mu[i];
    }
}

//整除分块,n,m版
ll aliquot_patition(ll n,ll m,ll d) {
    ll ans=0;
    int N=min(n,m);
    for(ll l=1,r; l<=N; l=r+1) {
        r=min(n/(n/l),m/(m/l));
        ans+=1ll*(n/(l*d))*(m/(l*d))*(summu[r]-summu[l-1]);
    }
    return ans;
}

int main() {
    sieve3(MAXN);
    int t;
    scanf("%d",&t);
    int n,m,d;
    while(~scanf("%d%d%d",&n,&m,&d)){
        printf("%lld
",aliquot_patition(n,m,d));
    }
}

https://www.luogu.org/problemnew/show/P2522

没事别用 long long ,常数卡死你!

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

#define MAXN 50000
int mu[MAXN+5];

int pri[MAXN+5],pritop;
bool notpri[MAXN+5];
//pritop从1开始计数

int summu[MAXN+5];

void sieve3(int n) {
    notpri[1]=mu[1]=1;
    for(int i=2; i<=n; i++) {
        if(!notpri[i])
            pri[++pritop]=i,mu[i]=-1;
        for(int j=1; j<=pritop&&i*pri[j]<=n; j++) {
            notpri[i*pri[j]]=1;
            //略有不同
            if(i%pri[j])
                mu[i*pri[j]]=-mu[i];
            else {
                mu[i*pri[j]]=0;
                break;
            }
        }
    }

    for(int i=1;i<=n;i++){
        summu[i]=summu[i-1]+mu[i];
    }
}

//整除分块,n,m版
int aliquot_patition(int n,int m,int d) {
    int ans=0;
    int N=min(n,m);
    for(int l=1,r; l<=N; l=r+1) {
        r=min(n/(n/l),m/(m/l));
        ans+=1ll*(n/(l*d))*(m/(l*d))*(summu[r]-summu[l-1]);
    }
    return ans;
}

int solve(int a,int b,int c,int d,int k){
    int sum1=aliquot_patition(b,d,k);
    int sum2=aliquot_patition(a-1,d,k);
    int sum3=aliquot_patition(b,c-1,k);
    int sum4=aliquot_patition(a-1,c-1,k);
    return sum1+sum4-sum2-sum3;
}

int main() {
    sieve3(MAXN);
    int t;
    scanf("%d",&t);
    int a,b,c,d,k;
    while(~scanf("%d%d%d%d%d",&a,&b,&c,&d,&k)){
        printf("%d
",solve(a,b,c,d,k));
    }
}

以上是关于模板 - 莫比乌斯反演的主要内容,如果未能解决你的问题,请参考以下文章

模板莫比乌斯反演

莫比乌斯反演

模板 - 莫比乌斯反演

莫比乌斯反演模板

[模板]莫比乌斯反演

模板 - 数学 - 数论 - 莫比乌斯反演 - 2