Luogu P2522 [HAOI2011]Problem b 莫比乌斯反演
作者:互联网
设$f(d)=\sum_{i=1}^N\sum_{j=1}^M[gcd(i,j)==d],\\F(n)=\sum_{n|d}f(d)=\lfloor \frac{N}{n} \rfloor \lfloor \frac{M}{n} \rfloor$
则$f(n)$
$=\sum_{n|d}\mu(\frac{n}{d})F(d)$
$=\sum_{n|d}\mu(\frac{n}{d})\lfloor \frac{N}{d} \rfloor \lfloor \frac{M}{d} \rfloor$
设$d=kn$
$=\sum_{k=1}^{min(\lfloor \frac{N}{n} \rfloor,\lfloor \frac{M}{n} \rfloor)}\space\mu(k)\lfloor \frac{N}{kn} \rfloor \lfloor \frac{M}{kn} \rfloor$
所以对$\lfloor \frac{N}{kn} \rfloor \lfloor \frac{M}{kn} \rfloor$整除分块,对$\mu(k)$搞一个前缀和。
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<cctype> #include<cstdlib> #include<vector> #include<queue> #include<map> #include<set> #define ll long long #define R register ll using namespace std; namespace Fread { static char B[1<<15],*S=B,*D=B; #define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++) inline int g() { R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix; do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix; } }using Fread::g; int n,a,b,c,d,x,cnt; int mu[50010],pri[25000]; bool v[50010]; inline void MU(int n) { mu[1]=1; for(R i=2;i<=n;++i) { if(!v[i]) pri[++cnt]=i,mu[i]=-1; for(R j=1;j<=cnt&&i*pri[j]<=n;++j) { v[i*pri[j]]=true; if(i%pri[j]==0) break; mu[i*pri[j]]=-mu[i]; } } for(R i=1;i<=n;++i) mu[i]+=mu[i-1]; } inline ll calc(int a,int b) { R ret=0; a>b?swap(a,b):void(0); for(R l=1,r;l<=a;l=r+1) { r=min(a/(a/l),b/(b/l)); ret+=(ll)(mu[r]-mu[l-1])*(a/l)*(b/l); } return ret; } signed main() { #ifdef JACK freopen("NOIPAK++.in","r",stdin); #endif MU(50000); n=g(); while(n--) { R ans=0; a=g()-1,b=g(),c=g()-1,d=g(),x=g(); printf("%lld\n",calc(b/x,d/x)-calc(a/x,d/x)-calc(b/x,c/x)+calc(a/x,c/x)); } }
2019.06.09
标签:lfloor,frac,sum,kn,rfloor,反演,HAOI2011,P2522,include 来源: https://www.cnblogs.com/Jackpei/p/10992742.html