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⇔(n−1)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 k−1个。
然后我们只需计算出: ∑ 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=2∑k⌊in⌋+i=2∑k⌊in−1⌋
因此可以用整除分块解决。
即:答案为: 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+k−1+i=2∑k⌊in⌋+i=2∑k⌊in−1⌋
时间复杂度: 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;
}