【杂题】[51Nod 1238] 最小公倍数之和 V3【数论】【杜教筛】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hzj1054689699/article/details/83347031

Description


i = 1 n j = 1 n l c m ( i , j ) \sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n} lcm(i,j)
n 1 0 10 n\leq 10^{10}

Solution

l c m lcm 拆开
原式化为
i = 1 n j = 1 n i j gcd ( i , j ) \sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n} {ij\over \gcd(i,j)}
d = gcd ( i , j ) , i = i / d , j = j / d d=\gcd(i,j),i=i/d,j=j/d
方便起见以下的除法默认为下取整
= d = 1 n d i = 1 n d j = 1 n d i j [ gcd ( i , j ) = 1 ] =\sum\limits_{d=1}^{n}d\sum\limits_{i=1}^{n\over d}\sum\limits_{j=1}^{n\over d} ij[\gcd(i,j)=1]

考虑对称性,有
= d = 1 n d × ( 2 ( i = 1 n d i j = 1 i j [ gcd ( i , j ) = 1 ] ) 1 ) =\sum\limits_{d=1}^{n}d\times \left(2\left(\sum\limits_{i=1}^{n\over d}i\sum\limits_{j=1}^{i} j[\gcd(i,j)=1]\right)-1\right)
(因为1被计算了2次,因此最后要-1)

我们知道,小于等于n且与n互质的数的和是 φ ( n ) n 2 φ(n)*n\over 2 (考虑一个小于等于n且与n互质的数i,显然n-i也与n互质,这样总共有 φ ( n ) 2 φ(n)\over 2 组)
1除外,小于等于1且与1互质的数的和是1,因此还要加上一个 1 2 1\over 2
因此又有
= d = 1 n d × ( 2 ( i = 1 n d φ ( i ) i 2 2 ) 1 + 1 2 × 2 ) =\sum\limits_{d=1}^{n}d\times \left(2\left(\sum\limits_{i=1}^{n\over d}{φ(i)*i^2\over 2}\right)-1+{1\over 2}\times 2\right)
= d = 1 n d × i = 1 n d φ ( i ) × i 2 =\sum\limits_{d=1}^{n}d\times \sum\limits_{i=1}^{n\over d}φ(i)\times i^2

f ( n ) = φ ( n ) n 2 f(n)=φ(n)·n^2
现在要做的就是求 f ( n ) f(n) 的前缀和 S ( n ) S(n)
考虑杜教筛

我们发现 f i d 2 = i d 3 f*id^2=id^3 (其中 * 为狄利克雷卷积),即 d n φ ( d ) d 2 ( n d ) 2 = n 2 d n φ ( d ) = n 3 \sum\limits_{d|n}φ(d)·d^2·\left({n\over d}\right)^2=n^2\sum\limits_{d|n}φ(d)=n^3

那么 i = 1 n i 3 = j = 1 n d j f ( n d ) d 2 \sum\limits_{i=1}^{n}i^3=\sum\limits_{j=1}^{n}\sum\limits_{d|j}f\left({n\over d}\right)d^2

接下来就是杜教筛套路做法,就不赘述了,直接贴上最终式子
s k ( n ) = i = 1 n i k s^k(n)=\sum\limits_{i=1}^{n}i^k
S ( n ) = s 3 ( n ) d = 2 n d 2 S ( n d ) S(n)=s^3(n)-\sum\limits_{d=2}^{n}d^2S\left({n\over d}\right)

这就直接分块做,根据数学知识(狗头)
有自然数平方和公式 s 2 ( n ) = n ( n + 1 ) ( 2 n + 1 ) 6 , s 3 ( n ) = ( n ( n + 1 ) 2 ) 2 s^2(n)={n(n+1)(2n+1)\over 6},s^3(n)=\left({n(n+1)\over 2}\right)^2

那么最终就是 A n s ( n ) = d = 1 n d S ( n d ) Ans(n)=\sum\limits_{d=1}^{n}d·S\left({n\over d}\right)

Code

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdlib>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define LL long long
#define mo 1000000007
#define N 5000005
using namespace std;
LL n,sm[N],ny6,ny2,h[N/10];
int pr[N/10],phi[N];
bool bz[N];
LL ksm(LL k,LL n)
{
	LL s=1;
	for(;n;n>>=1,k=k*k%mo) if(n&1) s=s*k%mo;
	return s;
}
LL squ(LL x)
{
	x%=mo;
	return(x*x%mo*(x+1)%mo*(x+1)%mo*ny2%mo*ny2%mo); 
}
LL sqr(LL x)
{
	x%=mo;
	return (x*(x+1)%mo*(2*x+1)%mo*ny6%mo);
}
void prp(int n)
{
	sm[1]=phi[1]=1;
	fo(i,2,n)
	{
		if(!bz[i]) pr[++pr[0]]=i,phi[i]=i-1;
		for(int j=1;j<=pr[0]&&i*pr[j]<=n;j++)
		{
			bz[i*pr[j]]=1;
			if(i%pr[j]==0)
			{
				phi[i*pr[j]]=phi[i]*pr[j];
				break;
			}
			phi[i*pr[j]]=phi[i]*(pr[j]-1);
		}
		sm[i]=(sm[i-1]+(LL)phi[i]*(LL)i%mo*(LL)i)%mo;
	}
}
LL get(LL m)
{
	if(m<=N-5) return sm[m];
	int p=n/m;
	if(h[p]) return h[p];
	h[p]=squ(m);
	LL d=2,d1,q;
	while(d<=m)
	{
		q=m/d,d1=m/q;
		h[p]=(h[p]-get(q)*(sqr(d1)-sqr(d-1))%mo+mo)%mo;
		d=d1+1;
	}
	return h[p];
}
int main()
{
	cin>>n;
	prp(N-5);
	ny6=ksm(6,mo-2),ny2=ksm(2,mo-2);
	LL d=1,d1,ans=0;
	while(d<=n)
	{
		LL m=n/d,d1=n/m;
		ans=(ans+(d+d1)%mo*(d1-d+1)%mo*ny2%mo*((get(m)+mo)%mo))%mo;
		d=d1+1;
	}
	printf("%lld\n",ans);
}

猜你喜欢

转载自blog.csdn.net/hzj1054689699/article/details/83347031
今日推荐