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\)

Output

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

Sample Input

5 3

Sample Output

7

HINT

\(50\%\)的数据满足:\(1 \le n, k le 1000\)
\(100\%\)的数据满足:\(1 \le n ,k \le 10^{9}\)

\(n\;mod\;i=n-i \times \lfloor \frac{n}{i} \rfloor\),因此我们可以对\(\lfloor \frac{n}{i} \rfloor\)相同的值的一块进行分块(\(\sqrt{n}\)块)。

#include<cstdio>
#include<cstdlib>
#include<iostream>
using namespace std;

typedef long long ll;

inline ll sum(ll a,ll b) { return (a+b)*(b-a+1)>>1; }

inline ll calc(ll n,ll m)
{
	ll ret = 0;
	if (m > n) ret = (m-n)*n,m = n;
	ll pos;
	for (ll i = 1;i <= m;i = pos+1)
	{
		pos = min(n/(n/i),m);
		ret += (pos-i+1)*n-sum(i,pos)*(n/i);
	}
	return ret;
}

int main()
{
	freopen("1257.in","r",stdin);
	freopen("1257.out","w",stdout);
	ll n,m;
	scanf("%lld %lld",&m,&n);
	printf("%lld",calc(n,m));	
	fclose(stdin); fclose(stdout);
	return 0;
}
posted @ 2015-03-07 22:02  lmxyy  阅读(222)  评论(0编辑  收藏  举报