LOJ #125. 除数函数求和 2 题解

博客介绍了LOJ #125题目的解法,主要涉及计算因数的k次方和(σk(x))以及利用整除分块技巧优化计算过程。通过推导公式并应用数学公式,实现了O(n)的时间复杂度解决方案。
摘要由CSDN通过智能技术生成

博客园同步

原题链接

简要题意:

求:

∑ i = 1 n 2 σ 2 ( i ) + 3 σ 1 ( i ) + 5 i \sum_{i=1}^n 2 \sigma_2(i) + 3 \sigma_1(i) + 5 i i=1n2σ2(i)+3σ1(i)+5i

其中 σ k ( x ) = ∑ i = 1 x i k [ x % i = = 0 ] \sigma_k(x) = \sum_{i=1}^x i^k [x \% i ==0] σk(x)=i=1xik[x%i==0],即 x x x 所有因数的 k k k 次方和。

推式子:

∑ i = 1 n 2 σ 2 ( i ) + 3 σ 1 ( i ) + 5 i \sum_{i=1}^n 2 \sigma_2(i) + 3 \sigma_1(i) + 5i i=1n2σ2(i)+3σ1(i)+5i

= ∑ i = 1 n ( 2 i 2 + 3 i + 5 ) × ⌊ n i ⌋ = \sum_{i=1}^ n (2i^2 + 3i + 5) \times \lfloor \frac{n}{i} \rfloor =i=1n(2i2+3i+5)×in

(计算每个因子 i i i 对其它数的贡献)

然后你发现这个式子和整除分块很像。

如果不会可以去 浅谈整除分块 学习一下呦。

好,现在会了 整除分块,你发现你需要高效计算的是:

∑ i = l r ( 2 i 2 + 3 i + 5 ) \sum_{i=l}^r (2i^2 + 3i+5) i=lr(2i2+3i+5)

= 2 × ∑ i = l r i 2 + 3 × ∑ i = l r i + 5 × ∑ i = l r 1 = 2 \times \sum_{i=l}^r i^2 + 3 \times \sum_{i=l}^r i + 5 \times \sum_{i=l}^r 1 =2×i=lri2+3×i=lri+5×i=lr1

= 2 × ( ∑ i = 1 r i 2 − ∑ i = 1 l − 1 i 2 ) + 3 × ( ∑ i = 1 r i − ∑ i = 1 l − 1 i ) + 5 × ( ∑ i = 1 r 1 − ∑ i = 1 l − 1 1 ) = 2 \times (\sum_{i=1}^r i^2 - \sum_{i=1}^{l-1} i^2) + 3 \times (\sum_{i=1}^r i - \sum_{i=1}^{l-1} i) + 5 \times (\sum_{i=1}^r 1 - \sum_{i=1}^{l-1} 1) =2×(i=1ri2i=1l1i2)+3×(i=1rii=1l1i)+5×(i=1r1i=1l11)

= 2 × ( r × ( r + 1 ) × ( 2 r + 1 ) 6 − l × ( l − 1 ) × ( 2 l − 1 ) 6 ) + 3 × ( r × ( r + 1 ) 2 − l × ( l − 1 ) 2 ) + 5 × ( r − l + 1 ) = 2 \times ( \frac{r \times (r+1) \times (2r+1)}{6} - \frac{l \times (l-1) \times (2l-1)}{6})+ 3 \times (\frac{r \times (r+1)}{2} - \frac{l \times (l-1)}{2}) + 5 \times (r-l+1) =2×(6r×(r+1)×(2r+1)6l×(l1)×(2l1))+3×(2r×(r+1)2l×(l1))+5×(rl+1)

然后你发现这可以 O ( 1 ) O(1) O(1) 计算。(学会小学数学公式真有用~)

时间复杂度: O ( n ) O(\sqrt{n}) O(n )

实际得分: 100 p t s 100pts 100pts.

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const ll MOD=998244353;

inline ll read(){char ch=getchar();ll f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
	ll x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}

ll n,ans=0;

inline ll count(ll l,ll r) {
	__int128 x=(((__int128)r*(r+1)*(2*r+1) - (__int128)(l-1)*l*(2*l-1))/3)%MOD; //平方
	x=(x<0)?(x+MOD):x;
	__int128 y=((__int128)(3*(l+r)*(r-l+1))/2)%MOD; //一次项
	y=(y<0)?(y+MOD):y;
	__int128 z=(5*(r-l+1))%MOD; //常数项
	z=(z<0)?(z+MOD):z;
	__int128 tot=(((__int128)(x+y+z)%MOD)*(n/l))%MOD; 
	return (ll)(tot<0)?(tot+MOD):tot;
} //好事多模

int main(){
	n=read();
	ll l=1,r;
	for(l=1;l<=n;l=r+1) { //整除分块模板
		r=n/(n/l);
		ans=(ans+count(l,r))%MOD;
	} printf("%lld\n",ans);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值