http://codeforces.com/contest/616/problem/E
给n,m,求Calculate the value of the sum: n mod 1 + n mod 2 + n mod 3 + ... + n mod m.
答案对1e9+7取模
一开始不知道怎么做,听了菊苣解说才会了。。。。
把 n%k看成 n-k*(n/k) n/k是指向下取整
那么sum= n*m - 【 1*n/1+ 2*n/2 + ...+ k*n/k +....m*n/m 】;
那么对于后面的部分,当k较小时,直接做,当k较大时,我们可以知道 会有 很多个数 的n/k值是同一个,我们枚举这个n/k值即可
// sum: k* [n/k],我们枚举n/k的值,我们称为A值
//从n/end,到n/sqt
//那么对于某个A值,n/A得到对应的起始数x,n/(A+1)得到对应的结束数y
//然后x到y都对应同一个A值,所以直接求x->y的和 乘上A即可
<span style="font-size:12px;">#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
const __int64 mod=1000000007;
__int64 min(__int64 a,__int64 b)
{return a<b?a:b;}
__int64 get (__int64 x)
{
x%=mod;
return (x+1)*x/2%mod;
}
__int64 deal_res(__int64 n,__int64 m)
{
__int64 end=min(n,m);
__int64 ret=0,i;
int sqt=sqrt(double(n));
for (i=1;i<=sqt&&i<=end;i++)
{
ret+=n/i*i; ret%=mod;
}
// sum: k* [n/k],我们枚举n/k的值,我们成为A值
//从n/end,到n/sqt
//那么对于某个A值,n/A得到对应的起始数x,n/(A+1)得到对应的结束数y
//然后x到y都对应同一个A值,所以直接求x->y的和 乘上A即可
sqt++;
for (i=n/sqt;i>=n/end;i--)
{
__int64 t1=n/i,t2=n/(i+1);
ret=(ret+ (get(min(end,t1))-get(t2))*i%mod )%mod;
}
return ret%mod;
}
int main()
{
__int64 n,m;
scanf("%I64d%I64d",&n,&m);
__int64 ans=m%mod*(n%mod)%mod;
__int64 res=deal_res(n,m);
ans-=res;
while (ans<0)
ans+=mod;
printf("%I64d\n",ans%mod);
return 0;
}</span>
// sum: k* [n/k],我们枚举n/k的值,我们称为A值
//从n/end,到n/sqt
//那么对于某个A值,n/A得到对应的起始数x,n/(A+1)得到对应的结束数y
//然后x到y都对应同一个A值,所以直接求x->y的和 乘上A即可
//从n/end,到n/sqt
//那么对于某个A值,n/A得到对应的起始数x,n/(A+1)得到对应的结束数y
//然后x到y都对应同一个A值,所以直接求x->y的和 乘上A即可