【BZOJ1257】余数之和(CQOI2007)-数论分块

测试地址:余数之和
做法:本题需要用到数论分块。
我们发现题目要求的就是:
i=1n(kkii)
我们知道ki只有不超过2k种取值。简单证明一下,当1ik时,ki显然最多只有k种取值,而当i>k时,1ki<k,也显然最多有k种取值,所以加起来最多有2k种取值。
因为ki只有不超过2k种取值,而函数f(i)=i的前缀和又十分好求,所以可以把上式分成2k段来计算,每段可以O(1)算出,这就是数论分块,时间复杂度为O(k)
(什么?我以前有写过数论分块?不存在的)
以下是本人代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,k;

int main()
{
    scanf("%lld%lld",&n,&k);

    ll ans=n*k;
    for(ll i=min(k,n);i>=1;i=k/(k/i+1))
    {
        ll l=k/(k/i+1)+1,r=i;
        ans-=(k/i)*(r*(r+1)/2-l*(l-1)/2);
    }
    printf("%lld",ans);

    return 0;
}
posted @ 2018-04-11 15:38  Maxwei_wzj  阅读(119)  评论(0编辑  收藏  举报