• 51Nod1222 最小公倍数计数


    1222 最小公倍数计数

    定义F(n)表示最小公倍数为n的二元组的数量。
    即:如果存在两个数(二元组)X,Y(X <= Y),它们的最小公倍数为N,则F(n)的计数加1。
    例如:F(6) = 5,因为[2,3] [1,6] [2,6] [3,6] [6,6]的最小公倍数等于6。

    给出一个区间[a,b],求最小公倍数在这个区间的不同二元组的数量。
    例如:a = 4,b = 6。符合条件的二元组包括:
    [1,4] [2,4] [4,4] [1,5] [5,5] [2,3] [1,6] [2,6] [3,6] [6,6],共10组不同的组合。

    输入

    输入数据包括2个数:a, b,中间用空格分隔(1 <= a <= b <= 10^11)。

    输出

    输出最小公倍数在这个区间的不同二元组的数量。

    输入样例

    4 6

    输出样例

    10

    SilverNebula的题解

    这种题显然要莫比乌斯反演!
    先不考虑(x≤y),最后答案加上(b-a+1)再除(2)即可。
    然后([a,b])又可以变成区间([1,b])的答案减([1,a-1])的答案。
    设:

    [ans(n)=sum_{i=1}^{n} sum_{j=1}^{n} [frac{i*j}{gcd(i,j)}le n] ]

    那么(ans(b)-ans(a-1))就是最终答案

    尝试化简上面的式子:

    [sum_{i=1}^{n} sum_{j=1}^{n} [frac{i*j}{gcd(i,j)}le n]\ =sum_{d=1}^{n} sum_{i=1}^{frac{n}{d}} sum_{j=1}^{frac{n}{d}} [i*jlefrac{n}{d}] [gcd(i,j)=1]\ =sum_{d=1}^{n} sum_{k=1}^{frac{n}{d}} mu(k) sum_{i=1}^{frac{n}{dk}} sum_{j=1}^{frac{n}{dk}} [i*k*j*klefrac{n}{d}]\ =sum_{k=1}^{n} mu(k) sum_{d=1}^{frac{n}{k}} sum_{i=1}^{frac{n}{dk}} sum_{j=1}^{frac{n}{dk}} [i*j*dlefrac{n}{k^2}] ]

    显然(d)(k)值大到一定程度,最后面就是0了,所以我们可以缩小求和上界:

    [sum_{k=1}^{sqrt n} mu(k) sum_{d=1}^{frac{n}{k^2}} sum_{i=1}^{frac{n}{dk^2}} sum_{j=1}^{frac{n}{dk^2}} [i*j*dlefrac{n}{k^2}] ]

    这个范围很友好,我们可以枚举(mu(k)),求满足条件的((d,i,j))三元组数量。
    需要求的三元组是无序的,为了不重不漏地计数,我们可以分别求出有序(单调上升)的三元组数量,对于其中三个数各不同的、有两个数相同的、三个数都相同的分别计数,然后乘以对应的排列数即可。

    时间复杂度(O(sum_{k=1}^{n^{frac 12}}(frac n{k^2})^frac 13)),积分近似一下是(O(n^frac 12))

    #include<bits/stdc++.h>
    #define il inline
    #define co const
    template<class T>T read(){
        T data=0,w=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
        for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
        return data*w;
    }
    template<class T>il T read(T&x) {return x=read<T>();}
    typedef long long LL;
    
    co int N=316300;
    int pri[N],tot,mu[N];
    void sieve(){
    	pri[1]=mu[1]=1;
    	for(int i=2;i<N;++i){
    		if(!pri[i]) pri[++tot]=i,mu[i]=-1;
    		for(int j=1;j<=tot&&i*pri[j]<N;++j){
    			pri[i*pri[j]]=1;
    			if(i%pri[j]==0){
    				mu[i*pri[j]]=0;
    				break;
    			}
    			mu[i*pri[j]]=-mu[i];
    		}
    	}
    }
    LL solve(LL n){
    	if(!n) return 0;
    	LL ans=0;
    	for(LL k=1;k*k<=n;++k)if(mu[k]){
    		LL lim=n/(k*k),sum=0;
    		for(LL i=1;i*i*i<=lim;++i){
    			for(LL j=i+1;j*j*i<=lim;++j)
    				sum+=(lim/(i*j)-j)*6+3;
    			sum+=(lim/(i*i)-i)*3+1;
    		}
    		ans+=mu[k]*sum;
    	}
    	return ans;
    }
    int main(){
    	sieve();
    	LL a=read<LL>(),b=read<LL>();
    	printf("%lld
    ",(solve(b)-solve(a-1)+b-a+1)/2);
    	return 0;
    }
    
  • 相关阅读:
    手机微信浏览器手动清楚浏览器缓存
    CSS 图像精灵怎么用(css sprites定位技术) 图标定位
    电商平台应该分析哪些数据?具体怎么去分析?
    酷家乐装修方案
    字体识别(根据图片截图识别字体) 求字体
    酿造系列:自己酿造夏日饮用的低度甜酒好喝吗?如何酿造?
    xcode Xcode_9.2.xip 官方离线下载地址
    nginx给server增加日志配置
    用monit监控mongodb,崩溃后自动重启mongdb
    电商产品经理进阶一:电商基础流程
  • 原文地址:https://www.cnblogs.com/autoint/p/11104913.html
Copyright © 2020-2023  润新知