BZOJ2301: [HAOI2011]Problem b

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2301

莫比乌斯函数,记录前缀和分块,然后容斥。

#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdio>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define maxn 50050
using namespace std;
int a,b,c,d,k,n,tot;
int sum[maxn],pri[maxn],mo[maxn],vis[maxn];
int read(){
    int x=0,f=1; char ch=getchar();
    while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
void getmo(){
    mo[1]=1;
    rep(i,2,50000){
        if (!vis[i]) vis[i]=1,pri[++tot]=i,mo[i]=-1;
        rep(j,1,tot){
            if (i*pri[j]>50000) break;
            vis[i*pri[j]]=1;
            if (i%pri[j]==0) {mo[i*pri[j]]=0; break;}
            else mo[i*pri[j]]=-mo[i];
        }
    }
    rep(i,1,50000) sum[i]=sum[i-1]+mo[i];
}
int go(int n,int m){
    int i=1,ans=0;
    while (i<=min(n,m)){
        int pos=min(n/(n/i),m/(m/i));
        ans+=(sum[pos]-sum[i-1])*(n/i)*(m/i);
        i=pos+1;
    }
    return ans;
}
int main(){
    getmo();
    n=read();
    rep(i,1,n){
        a=read(); b=read(); c=read(); d=read(); k=read(); a--; c--;
        a/=k; b/=k; c/=k; d/=k;
        printf("%d\n",go(b,d)+go(a,c)-go(a,d)-go(b,c));
    }
    return 0;
}

 

posted on 2015-12-01 20:34  ctlchild  阅读(147)  评论(0编辑  收藏  举报

导航