【51Nod1244】莫比乌斯函数之和-杜教筛+哈希表
测试地址:莫比乌斯函数之和
做法:这题需要使用杜教筛+哈希表。
以下方括号
首先我们设莫比乌斯函数前
将
因为
然而我们还可以优化一下:我们发现一些比较小的
以下是本人代码(25个测试点TLE了1个点,有待继续学习):
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define limit 1000000
#define mod 7500000
using namespace std;
ll a,b,h[mod+5]={0};
int miu[limit+5],sum[limit+5],f[mod+5];
bool prime[limit+5]={0};
int hash(ll x)
{
int s=x%mod;
while(h[s]&&h[s]!=x) s=(s+1)%mod;
return s;
}
void calc_miu(ll x)
{
for(int i=1;i<=x;i++)
miu[i]=1;
for(ll i=2;i<=x;i++)
if (!prime[i])
{
for(ll j=1;j*i<=x;j++)
{
prime[i*j]=1;
if (!(j%i)) miu[i*j]=0;
miu[i*j]*=-1;
}
}
sum[0]=0;
for(int i=1;i<=x;i++) sum[i]=sum[i-1]+miu[i];
}
ll count(ll x)
{
int pos=hash(x);
if (x<=limit) return (ll)sum[x];
if (h[pos]==x) return f[pos];
ll s=0,i=2,next;
while(i<=x)
{
next=x/(x/i);
s+=(next-i+1)*count(x/i);
i=next+1;
}
h[pos]=x,f[pos]=1-s;
return 1-s;
}
int main()
{
calc_miu(limit);
scanf("%lld%lld",&a,&b);
printf("%lld",count(b)-count(a-1));
return 0;
}