一.问题描述:
一个正整数数对(x, y),x,y满足条件:x和y均不大于n, 并且x除以y的余数大于等于k。输入n,k,请问满足条件的正整数数对有多少个?
二.注意事项:
输入包括两个正整数n,k(1 <= n <= 10^5, 0 <= k <= n - 1),从n的范围可以看出如果用两个for循环暴力解决问题,会超过题目要求的时间复杂度。
三.解题思路一:
1.如果输入的k为0,那么满足条件的正整数对有n*n对;
2.当y从k+1开始取值时,才能满足x%y>=k。例如,当k=3,n=11时,1%1=0;1%2=1;1%3=1;.....;11%3=2;
3.规律如下表
y=4 | n/y=2 | x=1,x=2,x=3,x=4,x=5,x=6,x=7,x=8,x=9,x=10,x=11 | 3=(11/4)*(4-3)+(11%4-3+1) |
y=5 | n/y=2 | x=1,x=2,x=3,x=4,x=5,x=6,x=7,x=8,x=9,x=10,x=11 | 4=(11/5)*(5-3) |
y=6 | n/y=1 | x=1,x=2,x=3,x=4,x=5,x=6,x=7,x=8,x=9,x=10,x=11 | 6=(11/6)*(6-3)+(11%6-3+1) |
四.解题思路一实现代码:
#include<iostream>
using namespace std;
int main()
{
long long n,k;
cin>>n>>k;
long long cnt=0;
if(k==0)
{
cnt=n*n;
}
else
{
for(long long y=k+1;y<=n;y++)
{
cnt+=(n/y)*(y-k)+(n%y>=k?n%y-k+1:0);
}
}
cout<<cnt<<endl;
return 0;
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
五.解题思路二:
当除数是y时,当x=1~n时,余数是1,2,3,,,y-1,0循环出现,循环节长度显然是y。例如当 n=11,y=3时:
x=1 | 1 |
x=2 | 2 |
x=3 | 0 |
x=4 | 1 |
x=5 | 2 |
x=6 | 0 |
x=7 | 1 |
x=8 | 2 |
x=9 | 0 |
x=10 | 1 |
x=11 | 2 |
那么我们可以枚举y=n~k(当y<k时所有的余数均小于k,因此不需要考虑)
然后对于x=1~n,总共出现了[n/y]个循环节,然后数出每个循环节里面不小于k的余数,最后再数出不满一个循环节的不小于k的余数,就是答案了。
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
long long n,k;
cin>>n>>k;
long long ans=0;
for(int y=max(1LL,k);y<=n;y++)
{
int res=0;
res=n/y*(y-k);
if(n%y>=k)
{
if(k)
res+=n%y-k+1;
else
res+=n%y;
}
ans+=res;
}
cout<<ans<<endl;
}