建信金科2020春招笔试编程题(精灵国人口统计)

题干

传说中有一个精灵国,国中有 A 个城镇,每个城镇中有 B 条街道,每条街道有 C 栋楼房,每个楼房有 D 间公寓,且城镇、街道、楼房、公寓都有唯一的整数编号,如城镇编号为1~A。现在国王想要统计精灵的人口,已知精灵只会住在满足以下所有条件的公寓中,请根据 A、B、C、D 来计算精灵人口:

  1. 公寓所在的城镇编号和街道编号的差值可以被 3 整除;
  2. 公寓所在的街道的编号和楼房的编号和值可以被 5 整除;
  3. 公寓所在的楼房的编号和城镇的编号的乘积可以被 4 整除;
  4. 公寓所在的城镇编号和公寓编号的最大公约数为 1。

输入:A B C D
输出:精灵数量
(ABCD之间以空格隔开,且 1<= A, B, C, D <= 60)

例:
输入:4 4 4 4
输出:8

解法一:暴力法(Java实现)

通过遍历每一个公寓对应的编号来寻找。

import java.util.Scanner;
public class Test {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int A = sc.nextInt();
		int B = sc.nextInt();
		int C = sc.nextInt();
		int D = sc.nextInt();
		int res = 0;
		for(int a = 1; a <= A; a++) {
			for(int b = 1; b <= B; b++) {
				for(int c = 1; c <= C; c++) {
					for(int d = 1; d <= D; d++) {
						int diff = Math.abs(a - b);
						if(isCoPrime(a,d) && diff % 3 == 0 && 
						(b+c) % 5 == 0 && (a*c) % 4 == 0) 
							res++;
					}
				}
			}
		}
		System.out.println(res);
	}
	//辗转相除法判断是否为互质数
	public static boolean isCoPrime(int num1, int num2) {
		if(num1 < num2) {
			int temp = num1;
			num1 = num2;
			num2 = temp;
		}
		int r = 0;
		while((r = num1 % num2) != 0) {
			num1 = num2;
			num2 = r;
		}
		if(num2 == 1) return true;
		else return false;
	}
}

其中,在判断两个数是否为互质数(最大公约数为1)时,使用到了辗转相除法(我是网上查的,看完顿感自己学业不精)。这里记录一下其中一种证明方法,妙哉。

证法一
a可以表示成a = kb + r(a,b,k,r皆为正整数,且r 假设d是a,b的一个公约数,记作d|a,d|b,即a和b都可以整除d。
而r = a - kb,两边同时除以d,r/d = a/d - kb/d = m,由等式右边可知m为整数,因此d|r。
因此d也是b,a mod b的公约数
假设d是b,a mod b的公约数, 则d|b, d|(a-k*b), 其中k是一个整数。
进而d|a.因此d也是a,b的公约数
因此(a,b)和(b,a mod b)的公约数是一样的,其最大公约数也必然相等,得证。
(来自百度百科:辗转相除法)

本人菜鸟一枚,目前只想到暴力法,还请大家指点更高阶的解法。

你可能感兴趣的:(面试笔试)