牛客多校第七场H(数论分块)

牛客多校第七场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... )的和

方法就是数论分块
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值