【题解】[CQOI2007] 余数求和 By 5ab as a juruo.

题目信息

题目来源:CCF 重庆省选 2007;

在线评测地址:Luogu#2261

运行限制:时间不超过 (1.00 extrm{s}),空间不超过 (128 extrm{MiB})

题目描述

给出正整数 (n)(k),请计算

[G(n,k) = sumlimits_{i=1}^n kmod i ]

其中 (kmod i) 表示 (k) 除以 (i) 的余数。

输入格式

输入只有一行两个整数,分别表示 (n)(k)

输出格式

输出一行一个整数表示答案。

数据规模与约定

  • 对于 (30\%) 的数据,保证 (n,kle 10^3)
  • 对于 (60\%) 的数据,保证 (n,kle 10^6)
  • 对于 (100\%) 的数据,保证 (1le n,kle 10^9)

分析

这道题又是一个十分经典的数论题。

(60 exttt{ pts})

直接暴力乱搞即可。

(100 exttt{ pts})

说实话这道题数据有那么亿点水。

我们来推个式子:

[egin{aligned} G(n,k)= & sumlimits_{i=1}^n kmod{i}\ =& sumlimits_{i=1}^nleft(k-leftlfloordfrac{k}{i} ight floor ight)\ =&\, nk-sumlimits_{i=1}^nleftlfloordfrac{k}{i} ight floor end{aligned} ]

后面那一半是经典的整数分块,直接 (mathcal{O}(sqrt{k})) 就可以解决。所以这道题的数据范围应该开到 1e14 然后再取模的吧

怎么证明整数分块的复杂度?

对于 (leftlfloordfrac{k}{i} ight floorle sqrt{k}) 的,值必然最多只有 (sqrt{k}) 个,所以这一部分是 (mathcal{O}(sqrt{k})) 的。

对于 (leftlfloordfrac{k}{i} ight floor > sqrt{k}) 的,则 (dfrac{k}{i}>sqrt{k}),可以得到 (i<dfrac{k}{sqrt{k}}=sqrt{k}),即这样的数的个数最多只有 (sqrt{k}) 个,一样是 (mathcal{O}(sqrt{k})) 的。

所以整体的复杂度是 (mathcal{O}(sqrt{k}))

注意事项

因为特殊的原因,这道题请将所有变量开 long long,否则会出大问题。

同时,别忘了整数分块中对 (r) 变量上界的把握。

Code

#include <cstdio>
using namespace std;

typedef long long ll;

ll my_min(ll a, ll b) { return (a < b)? a:b; } // 最小值函数

int main()
{
	ll l, r, n, k, ans;

	scanf("%lld%lld", &n, &k); // 输入
	ans = 1ll * n * k;

	for (l = 1; l <= n; l = r + 1) // 分块
	{
		if (k / l)
			r = my_min(k / (k / l), n); // 别忘了取最小值,否则只有 50 分
		else
			r = n;
		
		ans -= 1ll * (k / l) * (l + r) * (r - l + 1) / 2; // 统计进去
	}

	printf("%lld
", ans); // 输出

	return 0; // 然后就 AC 了、
}
原文地址:https://www.cnblogs.com/5ab-juruo/p/solution-cqoi2007_lg2261.html