[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 }
以上是关于[CQOI2007]余数求和的主要内容,如果未能解决你的问题,请参考以下文章