要说神仙数论题
老爷爷最强无敌
(咦怎么这么押韵的说)
题目大意:
给你
L,R,求有多少
n∈[L,R],满足存在
1≤a<b,c≥1,使得
n=abc。
1≤L≤R≤8×1016
题解:
首先当c确定时,为了避免重复计数,我们要保证a中的质因子的指数小于c。
其次,从这个角度出发,
c≥4都是没有意义的。
因为若
2∣c,则
n=a(b2)2c,否则
n=ab(b2)2c−1,可以验证这两种情况都是合法的。
若
c=2,则有
n=ab2>a3有
a<3n
,因此(令
p2(n),p3(n)分别表示n中是否含平方、立方因子)对答案的贡献是:
1≤a<3n
∑p2(a)(⌊an
⌋−a)
若
c=3,则这么计算是有问题的,因为例如
1×43=1×82,可能某些
c=3会被
c=2计算。
记
n=by3,我们知道其中一种可行但可能不合法的
c=2的情况是
n=by×y2。若想使得其可能合法,就要将
by中的平方质因子取尽,即要找到一个最大的
k,满足
k2∣by,并变换
n=k2by×(ky)2。
这样仍然可能是没有被计算的,因为
c=2的情况只会计算
k2by<ky的部分,也就是
k2by≥ky即
k≤3b
的部分是属于
c=3的答案但是不会被
c=2统计到。
因此我们可以类似的枚举
b,k,y来计算答案:
1≤b<4n
∑p3(b)b<y≤3bn
∑1≤k≤3b
∑[k2∣by]p2(k2by)
进一步简单的数论转化,令:
g=(k2,b),k′=gk2,b′=gb,y′=k′y
则:
[k2∣by]=[k′g∣b′gy]=[k′∣b′y]=[k′∣y]
同时:
p2(k2by)=p2(b′y′)=p2(b′)p2(y′)[b′⊥y′]
对后面的
[b′⊥y′]做莫比乌斯反演并化简整个式子(省略一些简单推导):
1≤b<4n
∑p3(b)1≤k≤3b
∑p2(b′)d∣b′∑μ(d)k′b<y′≤k′13bn
∑p2(y′)[d∣y′]
记
cntd(m)=∑i=1mp2(id),则上式等于:
1≤b<4n
∑p3(b)1≤k≤3b
∑p2(b′)d∣b′∑μ(d)(cntd(⌊k′d13bn
⌋)−cntd(⌊k′db⌋))
这样暴力枚举
b,k,d,可以大概算出复杂度不会并且远远不超过
O(n125),预处理前
O(n31)的
p2(n)以及前
O(n41)的
p3和
μ,还有
cntd(m)即可,其中
O(d)=O(n41),O(m)=O(d3n
)。
哇终于写(chao)完了
QwQ
#include<bits/stdc++.h>
#define gc getchar()
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define N3 440000
#define N4 100000
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
vector<int> dvs[N3],cnt[N4];
int p2[N3],p3[N3],mu[N3],pri[N3],mnp[N3],np[N3];
inline int gcd(int a,int b) { return a?gcd(b%a,a):b; }
inline int Mysqrt(lint x)
{
int L=1,R=1000000000,mid=(L+R)>>1;
while(L<=R)
{
if((lint)mid*mid<=x) L=mid+1;
else R=mid-1;mid=(L+R)>>1;
}
return R;
}
inline int Mycbrt(lint x)
{
int L=1,R=1000000,mid=(L+R)>>1;
while(L<=R)
{
if((lint)mid*mid*mid<=x) L=mid+1;
else R=mid-1;mid=(L+R)>>1;
}
return R;
}
inline lint calc(lint n)
{
if(!n) return 0;lint ans=0;
for(int a=1;(lint)a*a*a<n;a++)
if(p2[a]) ans+=Mysqrt(n/a)-a;
for(int b=1;(lint)b*b*b*b<n;b++) if(p3[b])
for(int k=1;k*k*k<=b;k++)
{
int k2dg=gcd(k*k,b),kp=k*k/k2dg,bp=b/k2dg;
if(!p2[bp]) continue;
Rep(i,dvs[bp])
{
int d=dvs[bp][i],s=b/kp,t=Mycbrt(n/b)/kp;
ans+=mu[d]*(cnt[d][t/d]-cnt[d][s/d]);
}
}
return ans;
}
inline int get_mnp_mu(int n)
{
mnp[1]=1,mu[1]=1;
for(int i=2,cnt=0;i<=n;i++)
{
if(!np[i]) pri[++cnt]=i,mnp[i]=i,mu[i]=-1;
for(int j=1;j<=cnt&&pri[j]<=n/i;j++)
{
int x=pri[j]*i;np[x]=1,mnp[x]=pri[j],mu[x]=-mu[i];
if(i%pri[j]==0) { mu[x]=0;break; }
}
}
return 0;
}
inline int prelude(lint n)
{
int n3=Mycbrt(n)+1,n4=Mysqrt(Mysqrt(n))+1;
get_mnp_mu(n3);
rep(i,1,n3)
{
p2[i]=p3[i]=1;int x=i;
while(x>1)
{
int t=mnp[x],cnt=0;while(x%t==0) x/=t,cnt++;
if(cnt>1) p2[i]=0;if(cnt>2) p3[i]=0;
if(!p2[i]&&!p3[i]) break;
}
}
rep(i,1,n4) rep(j,1,n4/i) if(mu[j]) dvs[i*j].pb(j);
rep(d,1,n4)
{
cnt[d].resize(n3/d+1),cnt[d][0]=0;
rep(i,1,(int)cnt[d].size()-1)
cnt[d][i]=cnt[d][i-1]+p2[i*d];
}
return 0;
}
int main()
{
lint L,R;cin>>L>>R;prelude(R);
return cout<<calc(R)-calc(L-1)<<endl,0;
}