码迷,mamicode.com
首页 > 其他好文 > 详细

题解 P2261 【[CQOI2007]余数求和】

时间:2019-09-12 21:47:21      阅读:91      评论:0      收藏:0      [点我收藏+]

标签:play   不能   int   inline   就是   证明   line   code   can   

题目链接

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;
}

题解 P2261 【[CQOI2007]余数求和】

标签:play   不能   int   inline   就是   证明   line   code   can   

原文地址:https://www.cnblogs.com/colazcy/p/11515120.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!