P3455 [POI 2007] ZAP-Queries
P3455 [POI 2007] ZAP-Queries - Description
有 \(T\) 组询问,每次给定正整数 \(n,m,d\),求
\[\sum_{i=1}^n\sum_{j=1}^m \left [ \gcd(i,j)=d \right ]
\]
\(1\le T,n,m,d\le 5\times 10^4\)。
P3455 [POI 2007] ZAP-Queries - Solution
\[\begin{aligned}
\sum_{i=1}^n\sum_{j=1}^m \left [ \gcd(i,j)=d \right ]&=
\sum_{i=1}^{\lfloor \frac{n}{d} \rfloor}\sum_{j=1}^{\lfloor \frac{m}{d} \rfloor} \left [ \gcd(i,j)=1 \right ]\\&=
\sum_{i=1}^{\lfloor \frac{n}{d} \rfloor}\sum_{j=1}^{\lfloor \frac{m}{d} \rfloor} \sum_{k\mid \gcd(i,j)} \mu(k)\\&=
\sum_{k=1}^n \mu(k)\sum_{k\mid i}^{\lfloor \frac{n}{d} \rfloor}\sum_{k\mid j}^{\lfloor \frac{m}{d}\rfloor}1\\&=
\sum_{k=1}^n \mu(k) \lfloor \frac{\lfloor \frac{n}{d} \rfloor}{k} \rfloor \lfloor\frac{\lfloor\frac{m}{d}\rfloor}{k}\rfloor\\&=
\sum_{k=1}^n \mu(k) \lfloor \frac{n}{kd} \rfloor \lfloor\frac{m}{kd}\rfloor
\end{aligned}
\]
考虑预处理出 \(\mu\) 函数,后面的二维整除分块即可,时间复杂度 \(O(T\sqrt{n})\)。
#include<bits/stdc++.h>
#define int long long
using namespace std;
long long T,n,m,d,ans;
long long Prime[50005],mu[50005],vis[50005],tot;
long long summu[50005];
inline void init(){
vis[1]=1;
mu[1]=1;
for(int i=2;i<=50000;i++){
if(!vis[i]){
Prime[++tot]=i;
mu[i]=-1;
}
for(int j=1;j<=tot&&i*Prime[j]<=50000;j++){
vis[i*Prime[j]]=1;
if(i%Prime[j]==0){
mu[i*Prime[j]]=0;
break;
}
mu[i*Prime[j]]=-mu[i];
}
}
for(int i=1;i<=50000;i++){
summu[i]=summu[i-1]+mu[i];
}
return;
}
signed main(){
cin>>T;
init();
while(T--){
ans=0;
cin>>n>>m>>d;
int qwq=min(n,m);
int r=1;
for(int l=1;l<=qwq/d;l=r+1){
r=min((n/d)/((n/d)/l),(m/d)/((m/d)/l));
int tmp=(n/d)/(l)*((m/d)/(l));
ans+=(summu[r]-summu[l-1])*(tmp);
}
cout<<ans<<endl;
}
return 0;
}

浙公网安备 33010602011771号