2018网易春招数对编程题(暴力版和优化版)

题目描述:
牛牛以前在老师那里得到了一个正整数数对(x, y), 牛牛忘记他们具体是多少了。

但是牛牛记得老师告诉过他x和y均不大于n, 并且x除以y的余数大于等于k。

牛牛希望你能帮他计算一共有多少个可能的数对。

输入描述:

输入包括两个正整数n,k(1 <= n <= 10^5, 0 <= k <= n - 1)。

输出描述:

对于每个测试用例, 输出一个正整数表示可能的数对数量。

示例:输入 5 2  输出:7

说明:满足条件的数对有(2,3),(2,4),(2,5),(3,4),(3,5),(4,5),(5,3)

   先来看一下暴力版的 ,因为比较简单,所以就没什么注释了

import java.util.Scanner;
public class Main1 {
	public static void main(String[] args) {
		@SuppressWarnings("resource")
		Scanner sc=new Scanner(System.in);
		int count = 0;
		int n = sc.nextInt();
		int k = sc.nextInt();
			for(int x=0;x<=n;x++) {
				for(int y=1;y<=n;y++) {
					if(x%y>=k) {
						count++;
						System.out.println("分别为"+"("+x+","+y+")");
					}
				}
			}
			System.out.println("数对值为"+count);
			
	}
}

因为有时间限制,所以暴力版肯定是不能通过的,二重循环的复杂度为O(n^2),可以使用一重循环实现如下,

注释都在代码里了,就不额外说明了

import java.util.Scanner;
public class Main2 {
	public static void main(String[] args) {
		
		Scanner sc=new Scanner(System.in);
		long count = 0;
		long n = sc.nextInt();
		long k = sc.nextInt();
		if(k==0) {
			count=n*n;
		}else {
			//由数学知识可知,除数>余数,又余数>=k,即除数>余数>=k,所以除数y>=k+1
			
			/*此时已经确定y的范围为[k+1,n],x为[1,n],将x分为n/y组
			 * x = [1,1……y-2,y],[y+1,……,2y-2,2y]……[……]……[……,n]
			 * 之所以这样分是为了在每个小区间上,每组第i个数%y的余数是i,这样x从1到n包含n/y个余数循环,每个余数循环中只有y-k个符合条件的。
			 * 最后剩下一个不完整的余数循环,判断这部分最大的余数是否大于k
			 */
			
			for(long y=k+1;y<=n;y++) {
				count+=(n/y)*(y-k);
				if(n%y>=k) {
					count+=n%y-k+1;
				}
			}
		}
		System.out.println("数值对数量为"+count);
	}
}

 

 

你可能感兴趣的:(2018网易春招数对编程题(暴力版和优化版))