[BZOJ 2301][HAOI2011]Problem b:莫比乌斯反演+容斥

点击这里查看原题

类似于BZOJ 1101,不过要多套个容斥
注意,a和c要先-1再/k(我因为先/k后-1 WA了一次)

/*
User:Small
Language:C++
Problem No.:2301
*/
#include<bits/stdc++.h>
#define ll long long
#define inf 999999999
using namespace std;
const int M=50005;
int mu[M],prime[M],cnt,a,b,c,d,k;
bool not_prime[M];
ll ans;
ll cal(int x,int y){
    if(x>y) swap(x,y);
    ll res=0;
    for(int i=1,r;i<=x;i=r+1){
        r=min(x/(x/i),y/(y/i));
        res+=(ll)(x/i)*(y/i)*(mu[r]-mu[i-1]);
    }
    return res;
}
void solve(){
    scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
    a--,c--;
    a/=k,b/=k,c/=k,d/=k;
    ans=cal(b,d)+cal(a,c)-cal(a,d)-cal(b,c);
    printf("%lld\n",ans);
}
int main(){
    freopen("data.in","r",stdin);//
    mu[1]=1;
    for(int i=2;i<M;i++){
        if(!not_prime[i]){
            prime[++cnt]=i;
            mu[i]=-1;
        }
        for(int j=1;j<=cnt&&i*prime[j]<M;j++){
            not_prime[i*prime[j]]=1;
            if(i%prime[j]==0){
                mu[i*prime[j]]=0;
                break;
            }
            mu[i*prime[j]]=-mu[i];
        }
    }
    for(int i=2;i<M;i++) mu[i]+=mu[i-1];
    int t;
    scanf("%d",&t);
    while(t--) solve();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/SmallSXJ/article/details/72841318