正题
题目要求这个东西
![\sum_{p\in prime} \sum_{i=1}^n \sum_{j=1}^m [gcd(i,j)=p]](https://i-blog.csdnimg.cn/blog_migrate/2c48a2920965ab6a74b770fc1784a742.png)
其实就是求![\sum_{p\in prime} \sum_{i=1}^{floor(n/p)} \sum_{j=1}^{floor(m/p)} [gcd(i,j)=1]](https://i-blog.csdnimg.cn/blog_migrate/b4256895d5f506d62dd76a33bc07fea2.png)
根据![\sum_{d\mid n}\mu(d)=[n=1]](https://i-blog.csdnimg.cn/blog_migrate/570584135ea712402ff995bdc92812c1.png)
换出来变成
枚举d变成
设
,那么就变成
发现做不了。
看一下后面的东西,我们把它设成
那么
很明显发现
prime函数指的是第i位是否为质数,是则为1,否则为0.
然后整除分块一下,预处理狄利克雷卷积。
然后n才1e7,按定义枚举
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
int T;
const int maxn=1e7;
int mu[maxn+10],q[maxn+10],P[maxn+10];
bool vis[maxn+10];
int n,m;
int main(){
scanf("%d",&T);
mu[1]=1;vis[1]=true;
for(int i=2;i<=maxn;i++){
if(!vis[i]) {P[++P[0]]=i;mu[i]=-1;}
for(int j=1;j<=P[0] && (long long) i*P[j]<=maxn;j++){
int temp=i*P[j];
vis[temp]=true;
if(i%P[j]==0) break;
mu[temp]=-mu[i];
}
}
for(int i=1;i<=P[0];i++)
for(int j=1;j<=maxn/P[i];j++) q[P[i]*j]+=mu[j];
for(int i=1;i<=maxn;i++) q[i]+=q[i-1];
while(T--){
scanf("%d %d",&n,&m);
if(m<n) swap(n,m);
int l=1,r,a,b;
long long ans=0;
while(l<=n){
a=n/(n/l);
b=m/(m/l);
r=min(a,b);
ans+=(long long)(n/l)*(m/l)*(q[r]-q[l-1]);
l=r+1;
}
printf("%lld\n",ans);
}
}

本文详细解析了一个数学算法竞赛题目,通过使用狄利克雷卷积和整除分块技巧,有效地解决了质数相关的问题。文章提供了完整的C++代码实现,并介绍了如何预处理质数和计算特定函数。
576

被折叠的 条评论
为什么被折叠?



