数论分块——余数之和

11 篇文章 0 订阅
7 篇文章 0 订阅

余数之和

题目链接
这道题目让我们求这样一个函数的值:F(n) = (n % 1) + (n % 2) + (n % 3) + … (n % n)
由于数据太大,直接暴力做会超时。因此,可以想办法将表达式进行转化:

∑ i = 1 n ( n % i ) = ∑ i = 1 n ( n − i ∗ ⌊ n i ⌋ ) = n ∗ n − ∑ i = 1 n i ∗ ⌊ n i ⌋ \sum_{i=1}^n(n\%i)=\sum_{i=1}^n(n-i*\lfloor\frac ni\rfloor)=n*n-\sum_{i=1}^ni*\lfloor\frac ni\rfloor i=1n(n%i)=i=1n(niin)=nni=1niin

我们容易发现最后转化的式子中,有我们比较熟悉的表达式 ⌊ n i ⌋ \lfloor\frac ni\rfloor in,因此,我们可以使用数论分块进行处理。这样再使用等差数列求和公式,就能求出求和表达式的值。

由于这道题目数据很大,会爆long long,因此要注意取模。

注意:在等差数列求和公式中,需要除以2,我在做题当中直接除以2,wa了好几次,因此这里改成了乘2的逆元。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
int main() 
{
	ll n;
	cin >> n;
	ll ans = (n % mod) * (n % mod) % mod;
	for (ll l = 1, r; l <= n; l = r + 1) {
		r = n / (n / l);
		if (r > n) r = n;
        ll pre = (n / l) % mod * ((r - l + 1) % mod) % mod, pr = (pre * ((r + l) % mod)) % mod;
        ans = ((ans - pr * (ll)500000004 % mod) % mod + mod) % mod;
	}
	cout << ans << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值