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 }

转载于:https://www.cnblogs.com/ykzou/p/4796096.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值