zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    MOSS中的User的Title, LoginName, DisplayName, SID之间的关系
    如何在Network Monitor中高亮间隔时间过长的帧?
    SharePoint服务器如果需要安装杀毒软件, 需要注意什么?
    如何查看SQL Profiler? 如何查看SQL死锁?
    什么是Telnet
    The name or security ID (SID) of the domain specified is inconsistent with the trust information for that domain.
    Windows SharePoint Service 3.0的某个Web Application无搜索结果
    网络连接不上, 有TCP错误, 如果操作系统是Windows Server 2003, 请尝试一下这里
    在WinDBG中查看内存的命令
    The virtual machine could not be started because the hypervisor is not running
  • 原文地址:https://www.cnblogs.com/autoint/p/11104913.html
Copyright © 2011-2022 走看看