这篇博客是我看到的关于这道题最详细的解释了。这道题比赛时队友找到了一种神奇的规律,大概是 ,然后也写过了,赛后发现本题的标答实际上是我们都没有想到的:
因为起点是 ,每次可以加上 也可以乘上 去传递,无论是加 还是乘 ,最后都不改变 的值,然后发现实际上需要求的是
考虑到整除分块解决的刚好是 ,那么我们就可以得出本题的求解通式:
需要注意的是为什么第二个式子是从 开始:因为本题一开始的 是从 开始的, 时在第一个式子已经计算过了 的情况,避免重复计算。为什么最后要加上 ,是因为 时 一定存在,因为 已经被计算过了,因此只需加上
#include <bits/stdc++.h>
#include <unordered_map>
#include <unordered_set>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define ins insert
#define Vector Point
#define lowbit(x) (x&(-x))
#define mkp(x,y) make_pair(x,y)
#define mem(a,x) memset(a,x,sizeof a);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const double dinf=1e300;
const ll INF=1e18;
const int Mod=1e9+7;
const int maxn=2e5+10;
ll cal(ll n,ll k){
ll ans=0;
for(ll l=2,r;l<=min(n,k);l=r+1){
r=min(k,n/(n/l));
ans=(ans+(r-l+1)%Mod*(n/l)%Mod)%Mod;
}
return ans;
}
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
ll n,k;
cin>>n>>k;
ll ans=n%Mod;
ans=(ans+cal(n,k))%Mod;
ans=(ans+cal(n-1,k))%Mod;
ans=(ans+k-1)%Mod;
cout<<ans<<endl;
return 0;
}