问题描述: 找(x, y)的对数。已知x、y均不大于n,且x%y大于k。输入n和k,输出满足条件的(x, y)有多少对。
思路1:暴力解(通过率为30%):
var line = readline().split(" ");
var n = parseInt(line[0]);
var k = parseInt(line[1]);
var count=0;
function isNum(n,k)
{
if(k===0)/*余数都是大于等于0的*/
{
count=n*n;
}
else
{
for (x=k;x<=n;x++)/*因为x%y>=k,所以被除数x肯定是要大于等于k的,我们让x从k开始*/
{
for (var y=k+1;y<=n;y++)/*因为除数要要大于余数的,所以y应该从k+1开始*/
{
if (x%y>=k)/*同时满足题目中要求的三个条件*/
{
count++;/*计数*/
}
}
}
}
return count;
}
print(isNum(n,k));
2、网上的优化算法:
首先被除数x 除数y 因为要求x%y>=k,则y一定是要大于k的(细想想!如果小于等于k了 余数不可能大于等于k的),所以k的取值应该从k+1到n;
然后看看可能的x有哪些。首先想,从1到n闭区间的范围内,可以划分为若干的段,比如[1,y] [y+1,2y] [2y+1,3y]……[my+1,n]
每个长度为y的段中,都有k个数([my+1,my+k))除以y的余数是小于k的,则这一段中余数大于等于k的有y-k个
所以统计,一共有n/y个长度为y的段,共有n/y*(y-k)个数字满足条件;
然后考虑最后剩余的那一段,即[mk+1,n],这段的长度为n%y,要判断其长度,如果大于k了,则说明有满足条件的数字,要统计其个数并加上;如果小于k则说明没有把满足条件的数字包含进来。
代码如下:
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
long n=sc.nextLong();
long k=sc.nextLong();
long count=0;
if(k==0){
System.out.println(n*n);
return;
}
//被除数x,除数y,因为x%y>+k, 所以k一定是大于k的
//思路来自于牛客用户:非全的春天
//对于每个y统计可能的x
for(long y=k+1;y<=n;y++){
//在每个长度为y的区间内,都有y-k个数字除以y后的余数大于等于k
count+=(n/y)*(y-k);
long temp=n%y;
//余下的数 区间长度如果大于k则要加上
if(temp>=k)
count+=temp-k+1;
}
System.out.println(count);
}
}