【洛谷】P2257 YY的GCD(莫比乌斯反演)
题意
组询问,每次询问求:
。
思路
不难想到枚举质数,将原式化简为:
按照套路,提出后面的 ,得到:
套用莫比乌斯函数,得到:
将莫比乌斯函数提到最前面去,得到:
后面的 其实就是在枚举 中 的倍数有多少个,那么其实就是 ,带入原式,得到:
到目前为止,利用数论分块,单次询问的复杂度为 。考虑进一步优化,设 ,带入原式:
枚举一下 ,提到式子的前方,得到:
发现后面那个式子可以预处理掉,于是复杂度就为 。
code:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e7+10;
#define LL long long
int f[N],mu[N],n,prime[N],tot;bool vis[N];LL sum[N];
void init()
{
mu[1]=1;
for(int i=2;i<N;i++)
{
if(!vis[i]) prime[++tot]=i,mu[i]=-1;
for(int j=1;j<=tot&&prime[j]*i<N;j++)
{
vis[prime[j]*i]=true;
if(i%prime[j]==0) {mu[prime[j]*i]=0;break;}
mu[prime[j]*i]=-mu[i];
}
}
for(int i=1;i<=tot;i++) for(int j=prime[i];j<N;j+=prime[i]) sum[j]+=mu[j/prime[i]];
for(int i=2;i<N;i++) sum[i]+=sum[i-1];
}
LL solve(int n,int m)
{
LL res=0;
for(int l=1,r=0;l<=min(n,m);l=r+1)
{
r=min(n/(n/l),m/(m/l));
res+=1ll*(n/l)*(m/l)*(sum[r]-sum[l-1]);
}
return res;
}
int main()
{
init();int n,m,T;scanf("%d",&T);while(T--) scanf("%d%d",&n,&m),printf("%lld\n",solve(n,m));
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】