其他分享
首页 > 其他分享> > BZOJ 1257: [CQOI2007]余数之和 数论专题第十四题

BZOJ 1257: [CQOI2007]余数之和 数论专题第十四题

作者:互联网

title

BZOJ 1257
Description

给出正整数n和k,计算j(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值
其中k mod i表示k除以i的余数。
例如j(5, 3)=3 mod 1 + 3 mod 2 + 3 mod 3 + 3 mod 4 + 3 mod 5=0+1+0+3+3=7

Input

输入仅一行,包含两个整数n, k。
1<=n ,k<=10^9

Output

输出仅一行,即j(n, k)。

Sample Input

5 3

Sample Output

7

analysis

用了一个看起来比较奇怪的方法
首先xmod&ThinSpace;&ThinSpace;i=x(int)(x/i)ix \mod i = x – (int)(x / i) * ixmodi=x–(int)(x/i)∗i,这个很好YY吧
然后可以找出每个(int)(x/i)(int)(x / i)(int)(x/i)相等的一段用等差数列求和来做。
可以证明最多分成sqrt(n)sqrt(n)sqrt(n)段——摘自hzwer

然而我是看《算阶》,再加上邱宇的讲解,嗯,就写出来了。。。。。

code

#include<bits/stdc++.h>
using namespace std;
template<typename T>inline void read(T &x)
{
    x=0;
    T f=1, ch=getchar();
    while (!isdigit(ch) && ch^'-') ch=getchar();
    if (ch=='-') f=-1, ch=getchar();
    while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
    x*=f;
}
int main()
{
    long long n,k,ans=0;
    read(n);read(k);
    ans=n*k;
    for (int x=1,gx; x<=n; x=gx+1)
    {
        gx=k/x?min(k/(k/x),n):n;
        ans-=(k/x)*(x+gx)*(gx-x+1)/2;
    }
    printf("%lld\n",ans);
    return 0;
}

标签:ch,int,sqrt,getchar,1257,isdigit,BZOJ,CQOI2007,mod
来源: https://blog.csdn.net/huashuimu2003/article/details/88874290