【51Nod1244】莫比烏斯函式之和-杜教篩+雜湊表
阿新 • • 發佈:2019-01-11
測試地址:莫比烏斯函式之和
做法:這題需要使用杜教篩+雜湊表。
以下方括號
首先我們設莫比烏斯函式前
將
因為
然而我們還可以優化一下:我們發現一些比較小的
以下是本人程式碼(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;
}