题意:
求∑i=1mn%i
。
思路:
n%i=n−[n/i]∗i
∑i=1mn%i=n∗m−∑i=1m[n/i]∗i
因为[n/i]…[n/j]在一段上是相等的,于是可以分段计算
j=[n/[n/i]]
http://codeforces.com/contest/616/problem/E
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define rep(i,a,b) for(int i = (a) ; i <= (b) ; i ++)
#define rrep(i,a,b) for(int i = (b) ; i >= (a) ; i --)
#define repS(it,p) for(auto it = p.begin() ; it != p.end() ; it ++)
#define repE(p,u) for(Edge * p = G[u].first ; p ; p = p -> next)
#define cls(a,x) memset(a,x,sizeof(a))
#define eps 1e-8
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e5+5;
const int MAXE = 2e5+5;
typedef long long LL;
typedef unsigned long long ULL;
int T,k;
LL n,m;
LL MOD = 1e9+7;
int fx[] = {0,1,-1,0,0};
int fy[] = {0,0,0,-1,1};
void input() {
}
LL tr(LL x) {
return x % MOD;
}
void solve() {
LL j ;
LL ans = tr(tr(n)*tr(m));
LL tmp = 0;
LL mm;
for(LL i = 1 ; i <= min(n,m) ; i ++) {
j = n / (n / i);
if(j > m) j = m;
if((i+j)%2==0) mm = tr((n/i)*tr(tr((i+j)/2)*tr(j-i+1)));
else mm = tr((n/i)*tr(tr((j-i+1)/2)*tr(i+j)));
tmp = tr(tmp+mm);
i = j;
}
ans = tr(ans - tmp);
if(ans < 0) ans += MOD;
printf("%I64d\n",ans);
}
int main(void) {
while(~scanf("%I64d %I64d",&n,&m)) {
input();
solve();
}
return 0;
}