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

题目大意

求有多少对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));
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值