zoukankan      html  css  js  c++  java
  • 51Nod1227 平均最小公倍数

    1227 平均最小公倍数

    Lcm(a,b)表示a和b的最小公倍数,A(n)表示Lcm(n,i)的平均数(1 <= i <= n),
    例如:A(4) = (Lcm(1,4) + Lcm(2,4) + Lcm(3,4) + Lcm(4,4)) / 4 = (4 + 4 + 12 + 4) / 4 = 6。
    F(a, b) = A(a) + A(a + 1) + ...... A(b)。(F(a,b) = ∑A(k), a <= k <= b)
    例如:F(2, 4) = A(2) + A(3) + A(4) = 2 + 4 + 6 = 12。
    给出a,b,计算F(a, b),由于结果可能很大,输出F(a, b) % 1000000007的结果即可。

    输入

    输入2个数a,b,中间用空格分隔(1 <= a <= b <= 10^9)。

    输出

    输出F(a, b) % 1000000007的结果。

    输入样例

    1 100

    输出样例

    122726

    题解

    [A(n)=frac 1nsum_{i=1}^n extrm{lcm(i,n)}=frac 1nsum_{i=1}^nfrac{in}{gcd(i,n)}\ =sum_{i=1}^nfrac i{gcd(i,n)}\ =sum_{d|n}sum_{i=1}^{frac nd}i[gcd(i,frac nd)=1] ]

    根据公式(sum_{i=1}^ni[gcd(i,n)=1]=frac{nvarphi(n)+e(n)}{2}),化简可得

    [A(n)=sum_{d|n}frac{frac ndvarphi(frac nd)+e(frac nd)}2\ frac 12(sum_{d|n}dvarphi(d)+1)\ F(n)=sum_{i=1}^nA(n)=sum_{i=1}^nfrac 12(sum_{d|i}dvarphi(d)+1)\ =frac 12left(sum_{i=1}^nsum_{d|i}dvarphi(d)+n ight) ]

    (dvarphi(d))就是(idcdot varphi),看起来非常眼熟。所以使用杜教筛套路,把枚举约数改为枚举倍数

    [F(n)=frac 12left(sum_{i=1}^nsum_{k=1}^{lfloorfrac ni floor}kvarphi(k)+n ight) ]

    (f(n)=nvarphi(n)),它的前缀和(S(n)=sum_{i=1}^nf(i))。则

    [F(n)=frac 12left(sum_{i=1}^nS(lfloorfrac ni floor)+n ight) ]

    只要能求出(S)就可以整除分块。于是构造(g=id),则

    [(f*g)(n)=sum_{d|n}f(n)g(frac nd)=sum_{d|n}dvarphi(d)frac nd\ =nsum_{d|n}varphi(d)=n^2 ]

    至此问题解决,上杜教筛即可。时间复杂度(O(n^frac 23))

    #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;
    using namespace std;
    
    co int N=1e6+1,mod=1e9+7,i2=500000004,i6=166666668;
    il int add(int a,int b){
    	return (a+=b)>=mod?a-mod:a;
    }
    il int mul(int a,int b){
    	return (LL)a*b%mod;
    }
    int pri[N],tot,phi[N];
    void init(){
    	pri[1]=phi[1]=1;
    	for(int i=2;i<N;++i){
    		if(!pri[i]) pri[++tot]=i,phi[i]=i-1;
    		for(int j=1;j<=tot&&i*pri[j]<N;++j){
    			pri[i*pri[j]]=1;
    			if(i%pri[j]==0){
    				phi[i*pri[j]]=phi[i]*pri[j];
    				break;
    			}
    			phi[i*pri[j]]=phi[i]*phi[pri[j]];
    		}
    	}
    	for(int i=2;i<N;++i) phi[i]=add(phi[i-1],mul(phi[i],i));
    }
    map<int,int> sf;
    int sum_f(int n){
    	if(n<N) return phi[n];
    	if(sf.count(n)) return sf[n];
    	int ans=mul(i6,mul(n,mul(n+1,2*n+1)));
    	for(int l=2,r;l<=n;l=r+1){
    		r=n/(n/l);
    		ans=add(ans,mod-mul(mul(i2,mul(l+r,r-l+1)),sum_f(n/l)));
    	}
    	return sf[n]=ans;
    }
    int solve(int n){
    	int ans=n;
    	for(int l=1,r;l<=n;l=r+1){
    		r=n/(n/l);
    		ans=add(ans,mul(r-l+1,sum_f(n/l)));
    	}
    	return mul(i2,ans);
    }
    int main(){
    	init();
    	int a=read<int>(),b=read<int>();
    	printf("%d
    ",add(solve(b),mod-solve(a-1))); // edit 1:mod
    	return 0;
    }
    
  • 相关阅读:
    Docker决战到底(三) Rancher2.x的安装与使用
    golang实现给图片加水印
    golang实现图片水印效果
    百度ueditor 编辑器使用问题收集
    重要的文件和数据,别放在/tmp下
    在CentOS 7上切换默认的java版本
    [转载]Centos和RedHat的区别和联系
    在Excel的公式框内输入换行符
    Outlook打不开,报错信息为“The time limit for logging on was reached while waiting for system resources. Try again. MAPI 1.0 [000004C2]”
    VMXNET3与E1000E与E1000的比较
  • 原文地址:https://www.cnblogs.com/autoint/p/11105629.html
Copyright © 2011-2022 走看看