bzoj2818Gcd 莫比乌斯反演

时间:2022-08-08 05:16:48

其实这题可以用欧拉函数做,我只是闲得蛋疼用反演而已。。
bzoj2818Gcd 莫比乌斯反演
最后那一坨分块搞一下就好了

#include<cstdio>
#include<algorithm>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int N=1e7+5;
ll n,ans,p[N],pri[N],mu[N];
int main()
{
int tot=0;
scanf("%lld",&n);
mu[1]=1;
fo(i,2,n)
{
if (!p[i])
{
pri[++tot]=i;
mu[i]=-1;
}
fo(j,1,tot)
{
if (pri[j]*i>n)break;
p[i*pri[j]]=1;
if (i%pri[j]==0)
{
mu[i*pri[j]]==0;
break;
}
else mu[i*pri[j]]=-mu[i];
}
mu[i]+=mu[i-1];
}
for(ll d=1;d<=tot&&pri[d]<=n;++d)
{
ll m=(ll)n/pri[d];
ll j=0;
for(ll i=1;i<=m;i=j+1)
{
j=min(m,m/(m/i));
ans+=(m/i)*(m/i)*(mu[j]-mu[i-1]);
}
}
printf("%lld\n",ans);
}