当前位置: 代码迷 >> 综合 >> BZOJ 2301: [HAOI2011]Problem b (莫比乌斯反演+分块+容斥)
  详细解决方案

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

热度:22   发布时间:2023-12-01 21:48:44.0

因为这里的a和c不一定为1,所以我们要使用容斥
并且因为询问组数较多,我们每次不能线性的使用莫比乌斯反演,我们要对区间进行分块
分块其实很简单,具体看代码吧

我的代码:

#include<cstdio>
#include<algorithm>
using namespace std;typedef long long ll;
const int maxn=50000+100;int mu[maxn],sum[maxn];
bool isprime[maxn];
int prime[maxn],tot;void init(){for(int i=0;i<maxn;i++) isprime[i]=true;isprime[0]=isprime[1]=false;tot=0;sum[0]=0;sum[1]=mu[1]=1;for(int i=2;i<maxn;i++){if(isprime[i]) prime[tot++]=i,mu[i]=-1;for(int j=0;j<tot && i*prime[j]<maxn;j++){isprime[i*prime[j]]=false;if(i%prime[j]) mu[i*prime[j]]=-mu[i];else break;}}for(int i=2;i<maxn;i++) sum[i]=sum[i-1]+mu[i];
}ll Mobius(int a,int b){if(a>b) swap(a,b);int pos;ll res=0;for(int i=1;i<=a;i=pos+1){pos=min(a/(a/i),b/(b/i));res+=(ll)(sum[pos]-sum[i-1])*(a/i)*(b/i);}return res;
}int main(){int n;scanf("%d",&n);init();while(n--){int a,b,c,d,k;scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);a--,c--; a/=k;b/=k;c/=k;d/=k;printf("%lld\n",Mobius(b,d)-Mobius(a,d)-Mobius(b,c)+Mobius(a,c));		}}
  相关解决方案