题目描述
牛牛以前在老师那里得到了一个正整数数对(x, y), 牛牛忘记他们具体是多少了。
但是牛牛记得老师告诉过他x和y均不大于n, 并且x除以y的余数大于等于k。
牛牛希望你能帮他计算一共有多少个可能的数对。
输入描述:
输入包括两个正整数n,k(1 <= n <= 10^5, 0 <= k <= n - 1)。
输出描述:
对于每个测试用例, 输出一个正整数表示可能的数对数量。
示例1
输入
5 2
输出
7
说明
满足条件的数对有(2,3),(2,4),(2,5),(3,4),(3,5),(4,5),(5,3)
思路:
朴素的做法是枚举n^2个点然后跟k作比较。这显然对n<=100000的规模来说是不允许通过的。
注意到当除数是y时,当x=1~n时,余数是1,2,3,…,y-1,0循环出现,循环节长度显然是y
那么我们可以枚举y=k+1~n(当y<=k时所有余数均小于k,因此不需要考虑)
然后对于x=1~n,总共出现了[n/y]个循环节,然后数出每个循环节里面不小于k的余数。最后再数出不满一个循环节的不小于k的余数(例如n=5,k=2,y=3先数出了5/3*(3-2),即(x,y)=(5,3),剩下(x,y)=(2,3)不足一个循环节的),就是答案了。
注意k=0时,对于y=1到n,都有x=1到n使之成立,因此此时ans=n*n
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
long long n,k;
cin>>n>>k;
int64_t ans=0;
for(int y=k+1;y<=n;++y)
{
int res=n/y*(y-k);
if(k!=0&&n%y>=k) res+=n%y-k+1;
ans+=res;
}
if(k==0)ans=n*n;
cout<<ans<<endl;
return 0;
}