BZOJ 1257 余数之和sum(分块优化)
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=46954
题意:f(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n,输入n, k,求f(n, k)。
思路:n>k的部分都为k,直接判断即可。n < k时,k mod n = k - k / n * n,观察发现在一定的区间[lhs, rhs]内k/i的值不变。那么就可以直接分块了, k/lhs * lhs + k/(lhs+1) * (lhs+1) + ... + k/(rhs+1)*(rhs+1)前一部分是相等的可以一次性处理,最后我们发现,在区间[i, k/(k/i)]这个区间内k/x的值不变。
code:
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 typedef long long LL; 5 int main() 6 { 7 LL n, k; 8 while (scanf("%lld %lld", &n, &k) != EOF) { 9 LL ans = 0; 10 if (n > k) { 11 ans += (n - k) * k; 12 n = k; 13 } 14 ans += n * k; 15 for (LL i = 1, la; i <= n; i = la + 1) { 16 la = min(n, k/(k/i)); // 得到区间上界 17 ans -= (k / i) * (i + la) * (la - i + 1) / 2; 18 } 19 printf("%lld\n", ans); 20 } 21 return 0; 22 }