题目大意
求有多少对a和b满足a<=b且l<=[a,b]<=r
数论题
区间[l,r]答案等于[1,r]-[1,l-1]
a<=b暂且不考虑。为了方便,接下来都不写下取整,出现除法即为整除。
∑ni=1∑nj=1[ij(i,j)<=n]
∑nd=1∑ni=1∑nj=1[(i,j)=d]∗[ijd<=n]
设i=i’d,j=j’d
∑nd=1∑ni′=1∑nj′=1[(i′,j′)=1]∗[i′j′d<=n]
我们反演一下,设k=(i’,j’),i’=i”k,j’=j”k
∑nk=1μ(k)∗∑ni′=1∑nj′=1∑nd=1[i′j′k2d<=n]
后面部分相当于一个子问题求多少对(a,b,c)满足abc<=n
设a<=b<=c,则
a<=n13
且
b<=na−−√
c的范围可以直接得到了。
因为原本abc是无序的,但是其实我们不能直接乘上3!,还需要讨论a=b=c或a=b!=c或a!=b=c三种情况。
最后注意没有考虑a<=b因此求出来无序,可以加上所有a=b的情况再除以2
#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=3000000+10;
int pri[maxn],mu[maxn];
bool bz[maxn];
int i,j,k,top;
ll n,m,l,t,ans;
void prepare(){
mu[1]=1;
fo(i,2,maxn-10){
if (!bz[i]) pri[++top]=i,mu[i]=-1;
fo(j,1,top){
if ((ll)i*pri[j]>maxn-10) break;
bz[i*pri[j]]=1;
if (i%pri[j]==0){
mu[i*pri[j]]=0;
break;
}
mu[i*pri[j]]=-mu[i];
}
}
}
ll calc(ll n){
ll a,b,c;
ll t=0;
fo(a,1,n){
if (a*a*a>n) break;
fo(b,a,n){
if (b*b*a>n) break;
t=t+(n/a/b-b+1)*6;
if (a==b) t=t-(n/a/b-b)*3;
if (a!=b) t-=3;
}
t-=5;
}
return t;
}
ll getans(ll n){
if (!n) return 0;
l=0;
fo(k,1,floor(sqrt(n)))
if (mu[k]){
t=calc(n/k/k);
l=l+mu[k]*t;
}
l=(l+n)/2;
return l;
}
int main(){
prepare();
scanf("%lld%lld",&m,&n);
printf("%lld\n",getans(n)-getans(m-1));
}