题目
给你一个n,一个k,k+1<=n<=1e5
问有多少对(a,b),a<=n且b<=n,且a%b>=k
输出这个对数
思路来源
https://blog.csdn.net/tong_zhi/article/details/79533298
题解
只有b比k大,余数才能大于等于k
所以枚举b,从k+1到n
b把区间[1,n]分成n/b个完整段,还可能最右有一个不完整段
[1,b][b+1,2b][2b+1,…][,n/b*b]左边完整的
[n/b*b+1,n]最右边不完整段
每个完整段里,只有[k,b-1]符合条件,ans+=(b-1-k+1)*n/b即可
对于那个不完整段,如果n%b>=k,说明[k,n%b],ans+=n%b-k+1即可
特判k=0,毕竟上述区间段里不包含0,a%b>=0说明a、b任取,n*n个
心得
被abc的D绊倒了我也是没有想到…
自己的思维题做的还是太少吧…
有的时候少刷那些高深的没用的…
你简单的都做不出来……
辣鸡比个自己
abc不认__int64和%I64d
cf不认%lld
真是各有偏好啊
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
typedef long long ll;
ll n,k;
ll solve()
{
if(!k)return n*n;//a、b任取,余数都大于等于0
ll ans=0;
for(int i=1;i<=n-k;++i)
{
ll b=k+i;//大于k的数才有余数k
//[1,b][b+1,2b][(n/b-1)*b+1,n/b*b]每个区间里
//这样的完整区间有n/b个,看右端点即可
//%b余数在[k,b-1]内是>=k的,而[k,b=(k+i-1)]长为i
ans+=(n/b)*i;
//不完整区间[(n/b)*b+1,n],[k,n%b]
if(n%b>=k)
ans+=n%b-k+1;
}
return ans;
}
int main()
{
scanf("%lld%lld",&n,&k);
printf("%lld\n",solve());
return 0;
}