P2522 [HAOI2011]Problem b
阿新 • • 發佈:2022-12-11
簡要題意
\(n\) 組資料,每組資料給定 \(a,b,c,d,k\),計算:
\[\sum_{i=a}^{b}\sum_{j=c}^{d}{[\gcd(i,j)=k]} \]\(a\leq b,c\leq d,1\leq n,a,b,c,d,k\leq5\times10^4\)。時間限制 \(2.5\operatorname{s}\)。
簡要題意
莫比烏斯反演基礎練習題。
首先容斥,令 \(f(x,y)=\sum_{i=1}^{x}\sum_{j=1}^{y}[\gcd(i,j)=k]\)。則原式化為:
\[f(b,d)-f(a-1,d)-f(b,c-1)+f(a-1,c-1) \]考慮化簡 \(f\)
先將 \(i,j\) 同時約去 \(k\),得:
\[\sum_{i=1}^{\lfloor\frac{x}{k}\rfloor}\sum_{j=1}^{\lfloor\frac{y}{k}\rfloor}[\gcd(i,j)=1] \]根據莫比烏斯函式性質:\(\sum_{d\mid x}{\mu(d)}=[x=1]\) 得:
\[\sum_{i=1}^{\lfloor\frac{x}{k}\rfloor}\sum_{j=1}^{\lfloor\frac{y}{k}\rfloor}\sum_{d\mid\gcd(i,j)}{\mu(d)} \]將第三個 \(\sum\) 的下限變形得:
將 \(d\) 提到前面去,得:
\[\sum_{d=1}^{\min(x,y)}\mu(d)\sum_{i=1}^{\lfloor\frac{x}{k}\rfloor}\sum_{j=1}^{\lfloor\frac{y}{k}\rfloor}[d\mid i][d\mid j] \]將右邊得兩個 \(\sum\) 化簡,得:
\[\sum_{d=1}^{\min(x,y)}\mu(d)\lfloor\frac{x}{dk}\rfloor\lfloor\frac{y}{dk}\rfloor \]數論分塊做即可。
時間複雜度 \(O(\max(b,d)+T\sqrt{\min(b,d)})\)。
注意,不要 #define int long long
!
程式碼
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
int mu[N],prime[N],tot;
long long sum[N];
bool vis[N];
int a,b,c,d,k,t;
inline void sieve(int bound){
mu[1]=1;vis[1]=1;
for(int i=2;i<=bound;i++){
if(!vis[i]){
prime[++tot]=i;
mu[i]=-1;
}
for(int j=1;j<=tot&&i*prime[j]<=bound;j++){
vis[i*prime[j]]=1;
if(i%prime[j]) mu[i*prime[j]]=-mu[i];
else{
mu[i*prime[j]]=0;
break;
}
}
}
for(int i=1;i<=bound;i++){
sum[i]=sum[i-1]+mu[i];
}
}
long long solve(int x,int y){
long long ret=0;
for(int i=1,j;i<=min(x,y);i=j+1){
j=min(x/(x/i),y/(y/i));
ret+=(1ll*x/(1ll*i*k))*1ll*(1ll*y/(1ll*i*k))*(sum[j]-sum[i-1]);
}
return ret;
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
sieve(5e4);
cin>>t;
while(t--){
cin>>a>>b>>c>>d>>k;
cout<<(solve(b,d)-solve(a-1,d)-solve(b,c-1)+solve(a-1,c-1))<<'\n';
}
return 0;
}