【Luogu】P2522Problemb(莫比乌斯反演)

  题目链接

  同Zip—Queries,但是用到容斥原理

  设f(n,m)是(x,y)的对数,其中1<=x<=n,1<=y<=m

  则有f(n,m)-f(a-1,n)-f(b-1,m)+f(a-1,b-1)就是(x,y)的对数,其中a<=x<=n,b<=y<=m

  然后就不多说啦

  放代码

  

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cctype>

using namespace std;

inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

long long miu[100200];
long long prime[100200],tot;
bool f[100200];

inline long long calc(long long n,long long m){
    long long x=1,top=min(n,m),ans=0;
    while(x<=top){
        long long y=min(n/(n/x),m/(m/x));
        ans+=(miu[y]-miu[x-1])*(n/x)*(m/x);
        x=y+1;
    }
    return ans;
}
        
int main(){
    miu[1]=1;
    for(int i=2;i<=100000;++i){
        if(!f[i]){
            prime[++tot]=i;
            miu[i]=-1;
        }
        for(int j=1;j<=tot&&(long long)i*prime[j]<=100000;++j){
            f[(long long)i*prime[j]]=1;
            if(i%prime[j])    miu[(long long)i*prime[j]]=-miu[i];
            else    break;
        }
    }
    for(int i=1;i<=100000;++i)    miu[i]+=miu[i-1];
    int T=read();
    while(T--){
        long long a=read(),b=read(),c=read(),d=read(),e=read();
        printf("%lld
",calc(b/e,d/e)-calc((a-1)/e,d/e)-calc((c-1)/e,b/e)+calc((a-1)/e,(c-1)/e));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/cellular-automaton/p/8004349.html