Solution [CQOI2007]余数求和
题目大意:给定\(n,k\),求\(\sum_{i = 1}^{n}k \bmod i\)
解析:我们考虑大力化柿子
\[\sum_{i = 1}^{n}k \bmod i\]
\[=\sum_{i = 1}^{n}k-i \times \lfloor \frac{k}{i} \rfloor\]
\[=nk-\sum_{i = 1}^{n}i \times\lfloor \frac{k}{i} \rfloor\]
然后我们发现右边\(\sum_{i = 1}^{n}i \times\lfloor \frac{k}{i} \rfloor\)这个东西不是很好求,跑去现学整除分块,我们发现\(\lfloor \frac{k}{i} \rfloor\)这个东西是可以分成很多块,每一块内的\(\lfloor \frac{k}{i} \rfloor\)是不变的,我们将其提出,就是一个等差数列求和了
对于一个左端点为\(l\),对于\(\lfloor \frac{k}{i} \rfloor\)分块的块,其右端点为\(r = \lfloor \frac{k}{\lfloor \frac{k}{l} \rfloor} \rfloor\),假如\(\lfloor \frac{k}{l} \rfloor = 0\)那么\(r = n\)(至于怎么证明这玩意儿我还真不会)
程序就很好写了,注意\(r\)不能超过\(n\)
代码:
#include <algorithm>
#include <cstdio>
using namespace std;
long long n,k,ans;
int main(){
scanf("%lld %lld",&n,&k);
ans = n * k;
for(long long l = 1,r;l <= n;l = r + 1)
r = (k / l == 0) ? n : min(n,k / (k / l)),ans -= (((l + r) * (r - l + 1)) >> 1) * (k / l);
return printf("%lld\n",ans),0;
}
原文地址:https://www.cnblogs.com/colazcy/p/11515120.html
时间: 2024-10-07 20:12:14