网易春招-数对

问题描述: 找(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、网上的优化算法:

https://blog.csdn.net/u013401204/article/details/80934463

首先被除数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);
}

}

你可能感兴趣的:(网易春招-数对)