1. 程式人生 > >1257: [CQOI2007]餘數之和sum(數學分段統計)

1257: [CQOI2007]餘數之和sum(數學分段統計)


如此一道水題,卻被邊界虐的很慘。
給定n和k,求sum  = k mod 1 + k mod 2 + k mod 3 + … + k mod n(1<=n ,k<=10^9);
列舉商(n/i),之後分出商相同的若干個區間,注意到每個區間都是一個等差數列,分段求和即可;

對於商i
左端點 l = n/(i+1)+1;
右端點 r = min(m,n/i);
然後求出每段的總和 :(n%l+n%r)*(r-l+1)/2;
下一個 i = n / (n/(i+1));

然後累加即可; 

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
using namespace std;
int main()
{
	long long n,m;
	scanf("%lld%lld",&m,&n);
	long long res(0);
	if(m>n) res+=(m-n)*n,m=n;
	for(long long i = 1; i <= n;)
	{
		long long r = min(m,n/i);
		long long l = (n/(i+1))+1;
		if(l<=r) res += (n%l+n%r)*(r-l+1)/2;
		if(i==n) break;
		i = n/(n/(i+1));
	}
	cout<<res<<endl;
	return 0;
}