H.Dividing(整除分块)

思路:整除分块.

显然题意可以转化为:求满足 n   m o d   k = 0 n\bmod k=0 nmodk=0 1 1 1的对数。

n   m o d   k = 1 ⇔ ( n − 1 )   m o d   k = 0 n\bmod k=1\Leftrightarrow (n-1)\bmod k=0 nmodk=1(n1)modk=0

对于特殊情况:

k = 1 k=1 k=1时有 n n n个, n = 1 , k > 1 n=1,k>1 n=1,k>1时有 k − 1 k-1 k1个。

然后我们只需计算出: ∑ i = 2 k ⌊ n i ⌋ + ∑ i = 2 k ⌊ n − 1 i ⌋ \sum\limits_{i=2}^k \lfloor\dfrac{n}{i}\rfloor+\sum\limits_{i=2}^k\lfloor\dfrac{n-1}{i}\rfloor i=2kin+i=2kin1

因此可以用整除分块解决。

即:答案为: n + k − 1 + ∑ i = 2 k ⌊ n i ⌋ + ∑ i = 2 k ⌊ n − 1 i ⌋ n+k-1+\sum\limits_{i=2}^k \lfloor\dfrac{n}{i}\rfloor+\sum\limits_{i=2}^k\lfloor\dfrac{n-1}{i}\rfloor n+k1+i=2kin+i=2kin1

时间复杂度: O ( k ) O(\sqrt{k}) O(k )

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double eps=1e-8;
const int mod=1e9+7;
ll n,k,ans=0;
void calc(ll n,ll k){
    for(ll l=2,r;l<=min(n,k);l=r+1){
        r=min(n/(n/l),k);
        ans=(ans+((r-l+1)%mod)*((n/l)%mod)%mod)%mod;
    }
}
int main(){
    scanf("%lld%lld",&n,&k);
    ans=(n+k-1)%mod;
    calc(n,k);
    calc(n-1,k);
    printf("%lld\n",ans);
    return 0;
}