http://www.elijahqi.win/2018/03/08/codeforces-616e/
题目描述
Calculate the value of the sum:
n
n mod
1
1 +
n
n mod
2
2 +
n
n mod
3
3 + … +
n
n mod
m
m . As the result can be very large, you should print the value modulo
10^{9}+7
109+7 (the remainder when divided by
10^{9}+7
109+7 ).
The modulo operator
a
a mod
b
b stands for the remainder after dividing
a
a by
b
b . For example
10
10 mod
3
3 =
1
1 .
输入输出格式
输入格式:
The only line contains two integers
n,m
n,m (
1<=n,m<=10^{13}
1<=n,m<=1013 ) — the parameters of the sum.
输出格式:
Print integer
s
s — the value of the required sum modulo
10^{9}+7
109+7 .
输入输出样例
输入样例#1: 复制
3 4
输出样例#1: 复制
4
输入样例#2: 复制
4 4
输出样例#2: 复制
1
输入样例#3: 复制
1 1
输出样例#3: 复制
0
将原式子转化
∑mi=1n (modi )=∑mi=1n−⌊ni⌋∗i ∑ i = 1 m n ( m o d i ) = ∑ i = 1 m n − ⌊ n i ⌋ ∗ i
观察到这个就是类似莫比乌斯的那个分块 因为n/i在很多地方都是重复的 所以我们可以在sqrt的时间内求出原式子的答案注意细节 比如比较n,m的大小
#include<cstdio>
#include<algorithm>
#define ll long long
#define mod 1000000007
using namespace std;
ll n,m,ans;
int main(){
// freopen("cf616e.in","r",stdin);
scanf("%lld%lld",&n,&m);
ans=n%mod*(m%mod)%mod;ll last=0;//printf("%lld\n",ans);
ll inv2=(mod-mod/2*1)%mod;
for (ll i=1;i<=min(n,m);i=last+1){
last=min(m,n/(n/i));ans-=(last-i+1)%mod*((i+last)%mod)%mod*inv2%mod*((n/i)%mod)%mod;
(ans+=mod)%=mod;
}printf("%lld\n",ans);
return 0;
}