洛谷P2257 YY的GCD
自律人切题了我也来水一道。
题目描述
多组数据,给定 \(n,m\),求
\[\sum_{x=1}^{n}\sum_{y=1}^{n}{[(x,y)\in \mathbb{P}]}
\]
其中 \(\mathbb P\) 表示质数集。
数据范围:\(n,m\le 10^7\)。
时间范围:\(4000\text{ms}\)。
Solution
不妨设 \(n\le m\)。
\[\begin{aligned}
&\sum_{x=1}^n\sum_{y=1}^m{[(x,y)\in \mathbb P]}\\
=&\sum_{p\in \mathbb P}\sum_{x=1}^{\lfloor\frac np\rfloor}\sum_{y=1}^{\lfloor\frac mp\rfloor}[(x,y)=1]\\
=&\sum_{p\in \mathbb P}\sum_{x=1}^{\lfloor\frac np\rfloor}\sum_{y=1}^{\lfloor\frac mp\rfloor}\sum_{k\mid x}\sum_{k\mid y}\mu(k)\\
=&\sum_{p\in \mathbb P}\sum_{k=1}^{\lfloor\frac np\rfloor}\mu(k)\lfloor\frac n{pk}\rfloor\lfloor\frac m{pk}\rfloor\\
=&\sum_{d=1}^{n}\lfloor\frac nd\rfloor\lfloor\frac md\rfloor\sum_{p\mid d\land p\in \mathbb P}\mu(\frac dp)
\end{aligned}
\]
我们发现 \(\sum\limits_{p\mid d\land p\in \mathbb P}\mu(\frac dp)\) 可以预处理前缀和,再套上数论分块即可解决。
时间复杂度为 \(O(n+T\sqrt n)\)。
Code
#include<cstdio>
using namespace std;
const int maxn=10000010;
template<class T>inline T Min(const T &a,const T &b){return a<b?a:b;}
int pri[maxn],tot,miu[maxn];
bool vis[maxn];
long long sum[maxn];
inline void Init(){
miu[1]=1;
for(int i=2;i<maxn;++i){
if(!vis[i])pri[++tot]=i,miu[i]=-1;
for(int j=1;i*pri[j]<maxn;++j){
vis[i*pri[j]]=1;
if(i%pri[j])miu[i*pri[j]]=-miu[i];
else break;
}
}
for(int i=2;i<maxn;++i)if(!vis[i])
for(int j=1;i*j<maxn;++j)
sum[i*j]+=miu[j];
for(int i=2;i<maxn;++i)sum[i]+=sum[i-1];
}
inline int get(int n,int l){
return n/(n/l);
}
int main(){
Init();
int T;scanf("%d",&T);
while(T--){
int n,m;
scanf("%d%d",&n,&m);
long long ans=0;
for(int l=1,r;l<=n&&l<=m;l=r+1){
r=Min(get(n,l),get(m,l));
ans+=(sum[r]-sum[l-1])*(n/l)*(m/l);
}
printf("%lld\n",ans);
}
return 0;
}

浙公网安备 33010602011771号