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; }