P2261 [CQOI2007]余数求和
题目给定柿子\(\displaystyle G(n,k)=\sum_{i=1}^{n}k\ mod\ i\)
我们知道\(mod\)是取模运算,即\(n\)整取\(k\)后的余数
∴我们设可以知道\(k\ mod\ i =k-i*\lfloor{\frac {k}{i}}\rfloor\)
∴我们的柿子就阔以变成这个亚子\(\displaystyle G(n,k)=\sum_{i=1}^{n}{k-i*\lfloor{\frac{k}{i}}\rfloor}\)
我们可以在把柿子简化一下
使这个柿子变成了\(\displaystyle n*k-\sum_{i=1}^{n}{i*\lfloor{\frac{k}{i}}\rfloor}\)
我们就不难发现我们只需要考虑降低一下后面这个\(\sum\)的复杂度了
我们考虑一个数\(k\)
我们发现当\(i>k\)的时候,那么\(\lfloor{\frac{k}{i}}\rfloor\)一定是等于\(0\)的
(因为分母比分子大了),所以我们在程序中判断一下\(k\)与\(i\)的大小关系就阔以了
然后我们考虑一下当\(i\leq k\)的时候呢,这个时候我们就要考虑一下\(\lfloor \frac{k}{i}\rfloor\)的数值的关系了
我们考虑一个数\(i\),且存在\(j=\lfloor \frac{k}{\lfloor \frac{k}{i}\rfloor}\rfloor\),我们就会发现\(\lfloor\frac{k}{j}\rfloor\)=\(\lfloor \frac{k}{i}\rfloor\),是不是很神奇?(读者可自行举栗子来验证一下)
我们会惊奇地发现:当\(i\)在\(i\)到\(\lfloor\frac{k}{\lfloor \frac{k}{i}\rfloor}\rfloor\)(即\(j\))的区间里所有\(\lfloor \frac{k}{i} \rfloor\)都会是同一个值
这其实是数论分块的一部分,这其实是个除法分块
然后放代码(较丑勿喷)
#include<bits/stdc++.h>
using namespace std;
long long ans, n, k;
int main(){
scanf("%lld%lld", &n, &k);
ans = n * k;
for(int i = 1, j = 1; i <= n; i = j + 1){
if(i <= k) j = min(n, k/ (k / i));//防止j越界
else break;//i > k时(k/i == 0) 直接退出
ans -= (k / i) * (j - i + 1) * (i + j) / 2;
}
printf("%lld\n", ans);
return 0;
}
完美结束,撒花✿✿ヽ(°▽°)ノ✿