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;
}
原文地址:https://www.cnblogs.com/autoint/p/11105629.html