[HAOI2011] Problem b
阿新 • • 發佈:2021-01-09
前言
板題一號
題目
題意:
求 \(\sum_{i=a}^b\sum_{j=c}^d[\gcd(i,j)=k]\)
講解
首先容斥
令 \(S(n,m)=\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=k]\)
則原式可化為 \(S(b,d)-S(a-1,d)-S(b,c-1)+S(a-1,c-1)\)
令 \(f(k)=\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=k]\),即 \(S(n,m)\)
\(F(k)=\sum_{d|k}f(k)=\lfloor\dfrac{n}{k}\rfloor\lfloor\dfrac{m}{k}\rfloor\)
\(f(k)=\sum_{k|d}\mu(\dfrac{d}{k})F(d)=\sum_{k|d}\mu(\dfrac{d}{k})\lfloor\dfrac{n}{d}\rfloor\lfloor\dfrac{m}{d}\rfloor\)
我們將 \(\dfrac{d}{k}\) 換元,得到:
\(f(k)=\sum_{i=1}^{\frac{\min(n,m)}{k}}\mu(i)\lfloor\dfrac{n}{ik}\rfloor\lfloor\dfrac{m}{ik}\rfloor\)
然後數論分塊即可
程式碼
int mu[MAXN],prime[MAXN],pn,s[MAXN]; bool vis[MAXN]; void sieve(int x) { s[1] = mu[1] = 1; for(int i = 2;i <= x;++ i) { if(!vis[i]) prime[++pn] = i,mu[i] = -1; for(int j = 1;j <= pn && i * prime[j] <= x;++ j) { vis[i * prime[j]] = 1; if(i % prime[j] == 0) break; mu[i * prime[j]] = -mu[i]; } s[i] = s[i-1] + mu[i]; } } int solve(int x,int y) { if(x>y) swap(x,y); int ret = 0; for(int l = 1,r;l <= x;l = r+1) { r = Min(x/(x/l),y/(y/l)); ret += (x / (l*k)) * (y / (l*k)) * (s[r] - s[l-1]); } return ret; } int main() { // freopen(".in","r",stdin); // freopen(".out","w",stdout); sieve(50000); for(int T = Read(); T ;-- T) { a = Read(); b = Read(); c = Read(); d = Read(); k = Read(); Put(solve(b,d) - solve(a-1,d) - solve(b,c-1) + solve(a-1,c-1),'\n'); } return 0; }