牛客多校第七场H:数论分块 + 思维
专题里面有,后悔没写,哭唧唧
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
ll n,k;
ll run(ll x){
ll j;/*i是前界,j是后界*/
ll res = 0;
for(ll i = 2;i <= min(x,k);i = j + 1){
ll y = x / i;
j = min(x / y,k);
/*右边界大于k在同一个n/i的数量上会有变化,会多加上几个n/i
右边界是可以大于k的,而且情况还不少,所以有时候不能直观去看
*/
res = (res + ((j - i + 1) * y) % mod);
}
return res;
}
int main(){
scanf("%lld%lld",&n,&k);
ll sum = 0;
sum += n + k - 1;
//如果数论分块会加上n + n - 1
//k不一定等于n,与实际不符
sum = (sum + run(n) + run(n - 1)) % mod;
printf("%lld\n",sum);
return 0;
}
/*
这道题是什么意思呢
就是通过观察,我们可以知道
(n,k)-->(nk,k) 第一个整数一定是第二个整数的倍数
(n,k)-->(nk+1,k)
令n = xk(第一个整数一定是k的倍数);
1. n == xk
2. n == xk + 1
那么n == xk 或n - 1 == xk
所以这道题就转化成了是求n / k(k = 1,2,3... )的和
方法就是数论分块
*/