测试地址:YY的GCD
题目大意:求
,
组询问,
。
做法:本题需要用到莫比乌斯反演+数论分块+分类讨论。
首先按照套路推式子(不妨设
):
令
,有:
互换
的位置,有:
这是一个数论分块的形式,如果我们能预处理出
,我们就可以以
的复杂度完成本题了。
直接枚举是
的,无法承受,而
显然并不是一个积性函数,这是不是就意味着我们无法用线性筛求了呢?不是的,只是我们需要进一步探求
的性质。
令
,其中
为
的最小质因子,我们尝试用和
有关的式子
算出
。
情况一:当
时,考虑在
式子中枚举的
:
当
时,显然
;
当
时,
包含因数
,所以
。
综上所述,
。
情况二:当
时,考虑在
式子中枚举的
:
当
时,显然
;
当
时,因为
是质数,且
,所以
和
互质,那么
和
显然也互质。又因为
是积性函数,所以
。将
提出和式后,发现剩下的就是
的表达式。
综上所述,
。
于是我们就可以用线性筛
求出
了,这样我们就解决了这一题。
以下是本人代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int T,prime[10000010];
ll mxn=0,n[10010],m[10010];
ll mu[10000010],g[10000010];
bool vis[10000010]={0};
void calc(int n)
{
mu[1]=1,g[1]=0;
prime[0]=0;
for(int i=2;i<=n;i++)
{
if (!vis[i])
{
prime[++prime[0]]=i;
mu[i]=-1;
g[i]=1;
}
for(int j=1;j<=prime[0]&&i*prime[j]<=n;j++)
{
vis[i*prime[j]]=1;
if (i%prime[j]==0)
{
mu[i*prime[j]]=0;
g[i*prime[j]]=mu[i];
break;
}
mu[i*prime[j]]=-mu[i];
g[i*prime[j]]=mu[i]-g[i];
}
}
for(int i=1;i<=n;i++)
g[i]+=g[i-1];
}
int main()
{
scanf("%d",&T);
for(int i=1;i<=T;i++)
{
scanf("%lld%lld",&n[i],&m[i]);
if (n[i]>m[i]) swap(n[i],m[i]);
mxn=max(mxn,n[i]);
}
calc(mxn);
for(int i=1;i<=T;i++)
{
ll ans=0;
for(ll j=n[i];j;j=max(n[i]/(n[i]/j+1),m[i]/(m[i]/j+1)))
{
ll l=max(n[i]/(n[i]/j+1),m[i]/(m[i]/j+1)),r=j;
ans+=(n[i]/j)*(m[i]/j)*(g[r]-g[l]);
}
printf("%lld\n",ans);
}
return 0;
}