Luogu P2522 [HAOI2011]Problem b
題意
\(n\) 組詢問,每組給定 \(a,b,c,d,k\),求 \(\sum\limits_{i=a}^{b}\sum\limits_{j=c}^{d}[\gcd(i,j)=k]\)。
\(\texttt{Data Range:}1\leq n,k\leq 5\times 10^4,1\leq a\leq b\leq 5\times 10^4,1\leq c\leq d\leq 5\times 10^4\)
題解
首先考慮二維差分一下,發現我們只需要求出類似於 \(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[\gcd(i,j)=k]\) 的東西就好了(這裡的 \(n\)
然後考慮推一下式子
\[\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[\gcd(i,j)=k]=\sum\limits_{i=1}^{\left\lfloor\frac{n}{k}\right\rfloor}\sum\limits_{j=1}^{\left\lfloor\frac{m}{k}\right\rfloor}[\gcd(i,j)=1] \]
然後發現可以莫反一下
\[\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[\gcd(i,j)=k]=\sum\limits_{i=1}^{\left\lfloor\frac{n}{k}\right\rfloor}\sum\limits_{j=1}^{\left\lfloor\frac{m}{k}\right\rfloor}\sum\limits_{d\mid\gcd(i,j)}\mu(d) \]
然後交換一下求和變數得到
\[\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[\gcd(i,j)=k]=\sum\limits_{d\mid\gcd(i,j)}\mu(d)\left\lfloor\frac{n}{dk}\right\rfloor\left\lfloor\frac{m}{dk}\right\rfloor \]
然後線性篩一下 \(\mu\) 的字首和就可以整除分塊做了。
程式碼
#include<bits/stdc++.h> using namespace std; typedef int ll; typedef long long int li; const ll MAXN=2e5+51; ll ptot,n,u,v,w,x,kk; ll np[MAXN],prime[MAXN],mu[MAXN],prefix[MAXN]; inline ll read() { register ll num=0,neg=1; register char ch=getchar(); while(!isdigit(ch)&&ch!='-') { ch=getchar(); } if(ch=='-') { neg=-1; ch=getchar(); } while(isdigit(ch)) { num=(num<<3)+(num<<1)+(ch-'0'); ch=getchar(); } return num*neg; } inline void sieve(ll limit) { np[1]=mu[1]=1; for(register int i=2;i<=limit;i++) { if(!np[i]) { prime[++ptot]=i,mu[i]=-1; } for(register int j=1;i*prime[j]<=limit;j++) { np[i*prime[j]]=1; if(i%prime[j]==0) { mu[i*prime[j]]=0; break; } mu[i*prime[j]]=-mu[i]; } } for(register int i=1;i<=limit;i++) { prefix[i]=prefix[i-1]+mu[i]; } } inline ll calc(ll n,ll m) { ll res=0; for(register int l=1,r;l<=min(n,m);l=r+1) { r=min(n/(n/l),m/(m/l)); res+=(prefix[r]-prefix[l-1])*(n/l/kk)*(m/l/kk); } return res; } int main() { n=read(),sieve(2e5+10); for(register int i=1;i<=n;i++) { u=read(),v=read(),w=read(),x=read(),kk=read(); printf("%d\n",calc(v,x)-calc(u-1,x)-calc(v,w-1)+calc(u-1,w-1)); } }