给出正整数n和k,计算j(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值。
例如j(5, 3)=3 mod 1 + 3 mod 2 + 3 mod 3 + 3 mod 4 + 3 mod 5=0+1+0+3+3=7。
输入格式
输入仅一行,包含两个整数n, k。
输出格式
输出仅一行,即j(n, k)。
数据范围
输入样例:
5 3
输出样例:
7
思路:看了大神的代码才学会的,方法是分块:
然后我们根据式子可以发现,难点在于 的求法,可以看出来的值在i变化时可能不会发生改变,所以我们思考是否能够通过求 的变化范围进而求值。想到这一步必须先证明 中的值的确是很有限的,与不在一个量级上,事实证明确实是这样的,考虑的取值从的情况,因为该段有个取值,所以在该段的最多有个取值,然后考虑的情况,观察发现当取时那就证明了在段上,也最多仅有个取值;
然后我们现在就是求对于的每一个取值的上下界,设一个取值的下界是那么上界会是什么呢?
设(左边不一定是整数)观察到我们如果想让的取值不发生变化,那么我们取能得到最大的,这里的思路也是这样,上界取这里就代表这个的取值;
随后再加一个等差数列求和公式;
/*************************************************************************
> File Name: Acwing.cpp
# Author: Badwoman
# mail: 1194446133@qq.com
> Created Time: 2020年12月21日 星期一 10时41分06秒
************************************************************************/
#include<set>
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#define ll long long
#define ull unsigned long long
#define pb push_back
#define mp make_pair
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define bep(i,a,b) for(int i=a;i>=b;--i)
#define lowbit(x) (x&(-x))
using namespace std;
ll n,k;
void solve(){
scanf("%lld%lld",&n,&k);
ll ans = n*k,r;
for(ll l=1;l<=n;l = r+1){
if(k/l == 0)break;
r = min(n,k/(k/l));
ll p = k/l;
ans -= p*(r-l+1)*(l+r)/2;
}
printf("%lld\n",ans);
}
int main(){
solve();
return 0;
}