[CQOI2007]余数求和

Posted mrclr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CQOI2007]余数求和相关的知识,希望对你有一定的参考价值。

嘟嘟嘟

 

题中就是让求 ∑k % i (i : 1~n).又知道,k % i = k - i * ?k / i?,则 ∑k % i = ∑ k - i * ?k / i? = n * k - ∑ i * ?k / i?.

观察?k / i?,会发现相等的都是连续的一段,因此可以分块处理每一个?k / i?相等的一段。枚举[l, r]中的l,令 t = ?k / l?,如果t != 0,则 r = min(n, k / t) ;否则r = n。

令 k / l = m,则 m * l + mod1 = k,又因为m * r + mod2 = k,要令r最大,则mod2 = 0,因此m * r = k,联立得 r = k / ?k / l?. 

当t = 0的时候,就是枚举到l > k,那么剩下的都是0了,直接break。

技术分享图片
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<cctype>
 8 #include<vector>
 9 #include<stack>
10 #include<queue>
11 using namespace std;
12 #define enter puts("") 
13 #define space putchar(‘ ‘)
14 #define Mem(a) memset(a, 0, sizeof(a))
15 typedef long long ll;
16 typedef double db;
17 const int INF = 0x3f3f3f3f;
18 const int eps = 1e-8;
19 //const int maxn = ;
20 inline ll read()
21 {
22     ll ans = 0;
23     char ch = getchar(), last =  ;
24     while(!isdigit(ch)) {last = ch; ch = getchar();}
25     while(isdigit(ch)) {ans = ans * 10 + ch - 0; ch = getchar();}
26     if(last == -) ans = -ans;
27     return ans;
28 }
29 inline void write(ll x)
30 {
31     if(x < 0) x = -x, putchar(-);
32     if(x >= 10) write(x / 10);
33     putchar(x % 10 + 0);
34 }
35 
36 ll n, k, sum = 0;
37 
38 int main()
39 {
40     n = read(); k = read();
41     for(ll l = 1, r = 1; l <= n && k / l; l = r + 1)
42     {
43         r = min(k / (k / l), n);
44         sum -= (r + l) * (r - l + 1) * (k / l) >> 1;
45     }
46     write(sum + n * k); enter;
47     return 0;
48 }
View Code

 

以上是关于[CQOI2007]余数求和的主要内容,如果未能解决你的问题,请参考以下文章

p2261 [CQOI2007]余数求和

题解CQOI2007余数求和

[CQOI2007]余数求和-整除分块

[CQOI2007]余数求和

题解 P2261 [CQOI2007]余数求和

[CQOI2007]余数求和