P2522 [HAOI2011]Problem b(莫比乌斯反演)

就在例题的基础上加个容斥。注意循环部分不要开long long ,时间会极大幅度的增长。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+100;
typedef long long ll;
int vis[maxn];
int pri[maxn],mu[maxn],sum[maxn],cnt;
void getMu (ll n) {
	mu[1]=1;
	for (ll i=2;i<=n;i++) {
		if (!vis[i]) {
			mu[i]=-1;
			pri[++cnt]=i;
		}
		for (ll j=1;j<=cnt&&i*pri[j]<=n;j++) {
			vis[i*pri[j]]=1;
			if (i%pri[j]==0) break;
			else mu[i*pri[j]]=-mu[i];
		}
	}
	for (ll i=1;i<=n;i++) sum[i]=sum[i-1]+mu[i];
}  
int solve (int a,int b,int d) {
	if (a>b) swap(a,b);
	int ans=0;
	for (ll l=1,r;l<=a;l=r+1) {
		r=min(a/(a/l),b/(b/l));
		ans+=(a/(l*d))*(b/(l*d))*(sum[r]-sum[l-1]);
	}
	return ans;
} 
main () {
	int _;
	scanf("%d",&_);
	getMu(60000);
	while (_--) {
		int a,b,c,d,e;
		scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);
		int ans=solve(b,d,e)-solve(b,c-1,e)-solve(a-1,d,e)+solve(a-1,c-1,e);
		printf("%lld\n",ans);
	}
}
posted @ 2021-07-12 13:32  zlc0405  阅读(28)  评论(0编辑  收藏  举报