题干
传说中有一个精灵国,国中有 A 个城镇,每个城镇中有 B 条街道,每条街道有 C 栋楼房,每个楼房有 D 间公寓,且城镇、街道、楼房、公寓都有唯一的整数编号,如城镇编号为1~A。现在国王想要统计精灵的人口,已知精灵只会住在满足以下所有条件的公寓中,请根据 A、B、C、D 来计算精灵人口:
- 公寓所在的城镇编号和街道编号的差值可以被 3 整除;
- 公寓所在的街道的编号和楼房的编号和值可以被 5 整除;
- 公寓所在的楼房的编号和城镇的编号的乘积可以被 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<b),则r = a mod b
假设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)的公约数是一样的,其最大公约数也必然相等,得证。
(来自百度百科:辗转相除法)
本人菜鸟一枚,目前只想到暴力法,还请大家指点更高阶的解法。