[51nod 1222]最小公倍数计数

来源:互联网 发布:8051单片机引脚映射 编辑:程序博客网 时间:2024/04/29 18:49

题目大意

求有多少对a和b满足a<=b且l<=[a,b]<=r

数论题

区间[l,r]答案等于[1,r]-[1,l-1]
a<=b暂且不考虑。为了方便,接下来都不写下取整,出现除法即为整除。
ni=1nj=1[ij(i,j)<=n]
nd=1ni=1nj=1[(i,j)=d][ijd<=n]
设i=i’d,j=j’d
nd=1ni=1nj=1[(i,j)=1][ijd<=n]
我们反演一下,设k=(i’,j’),i’=i”k,j’=j”k
nk=1μ(k)ni=1nj=1nd=1[ijk2d<=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));}
0 0