若
,
;若
,
。所以我们只需要考虑
的情况。
那么能表示成
的很好求,就是
。现在考虑求只能被表示成
的数的个数。
我们设
是满足
的最大值,那么
,也就是要满足
即
。设
当
有三次因子时为
,否则为
,那么式子就是:
为了处理那个整除,设 ,式子化成:
因为 ,就有:
其中 用莫比乌斯反演弄掉就是:
那么可以发现 ,对于每个 预处理其在 内(因为 )所有倍数 的 的前缀和,这样复杂度大概是 的。那么我们直接枚举 ,因为 ,所以复杂度是 ,其中 表示质因子个数,但其实并没有这么满,是可以过的。
注意直接调用pow函数可能存在精度问题,调用之后左右再判一下即可。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#define PB push_back
#define N4 17000
#define N3 440000
#define ll long long
using namespace std;
vector<int> w[N4+5];
int minp[N3+5],pri[N3+5],mu[N3+5],r[10],num;
bool c[N3+5],d[N3+5];
void getpri(int n)
{
for(int i=1;i<=n;i++)
minp[i]=i;
mu[1]=1;
for(int i=2;i<=n;i++)
{
if(minp[i]==i){mu[i]=-1;pri[++num]=i;}
for(int j=1;j<=num&&i*pri[j]<=n;j++)
{
minp[i*pri[j]]=pri[j];
if(i%pri[j]==0) {mu[i*pri[j]]=0;break;}
mu[i*pri[j]]=-mu[i];
}
}
}
void init()
{
memset(c,1,sizeof(d));
for(int i=1;i<=N3;i++)
for(int t=i,p=0,k=0;t>1;t=t/minp[t])
{
if(minp[t]!=p) p=minp[t],k=0;
k++;
c[i]&=(k<3);
}
for(int i=1;i<=N4;i++)
{
w[i].PB(0);
for(int j=i;j<=N3;j+=i)
w[i].PB(mu[j]*mu[j]);
for(int j=1;j<w[i].size();j++)
w[i][j]+=w[i][j-1];
}
}
int gcd(int x,int y)
{
for(int t;y;t=x,x=y,y=t%y);
return x;
}
int root(ll n,int x)
{
int r=pow(n,1.0/x);
for(;(ll)r*r*(x==3?r:1)<=n;r++);
for(;(ll)r*r*(x==3?r:1)>n;r--);
return r;
}
ll solve(ll n)
{
ll ans=0;
for(int a=1;(ll)a*a*a<=n;a++)
if(mu[a]*mu[a])
{
int tmp=root(n/a,2)-a;
if(tmp<=0) break;
ans+=tmp;
}
for(int a=1;(ll)a*a*a*a<=n;a++)
if(c[a])
for(int k=1;k*k*k<=a;k++)
{
int g=gcd(k*k,a),a1=a/g,k1=k*k/g;
if(mu[a1]!=0)
{
int top=0;
for(int t=a1;t>1;t=t/minp[t]) r[top++]=minp[t];
for(int s=0;s<(1<<top);s++)
{
int e=1;
for(int i=0;i<top;i++)
if((s>>i)&1) e=e*r[i];
int L=a/k1,R=root(n/a,3)/k1;
if(mu[e]==0||R/e<=L/e) continue;
ans+=(ll)mu[e]*(w[e][R/e]-w[e][L/e]);
}
}
}
return ans;
}
int main()
{
getpri(N3);
init();
ll l,r,tmp;
scanf("%lld%lld",&l,&r);
printf("%lld",solve(r)-solve(l-1));
return 0;
}