【BZOJ2820】YY的GCD-莫比乌斯反演+数论分块+分类讨论
测试地址: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;
}