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>