洛谷 P2261 [CQOI2007] 余数求和 (等差数列,整除分块)

 一开始一直wa,没搞明白为啥,后来知道了

首先,num计算的是某一个商的个数,但是 k / (k / l)计算的是小于等于该商的个数,需要减去前面的

其次,最后可能num的个数并没有达到,也就是说有一部分数字也能得到当前的商,但是超出了 n 的边界,取个最小值就ok了

#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
int main()
{
	ll n, k;
	scanf("%lld %lld", &n, &k);
	ll sq = sqrt(k);
	ll l, r;
	ll res = n * k;
	for (ll l = 1, r; l <= n; ){
		if(k / l == 0)break;
		ll num = k / (k / l);
		num = num - l + 1;
		num = min(num, n - l + 1);
		ll sum = num * (num - 1) / 2 +num * l;
		res -= sum * int(k / l);
		l += num;
	}
	printf("%lld\n", res);
	return 0;
}

 

posted @ 2019-08-19 20:20  correct  阅读(119)  评论(0)    收藏  举报