/**
* 找出四位数的所有吸血鬼数字
* 吸血鬼数字是指位数为偶数的数字,可以由一对数字相乘而得到,而这对数字各包含乘积的一半位数的数字,其中从最初的数字中选取的数字可以任意排序.
* 以两个0结尾的数字是不允许的。
* 例如下列数字都是吸血鬼数字
1260=21*60
1827=21*87
2187=27*81
…
* 比较笨的低效率的做法: 遍历所有四位数, 每生成一个四位数的时候,
* 在双重循环遍历两位数,在两位数的内层循环中判断是否与最外层循环的四位数相等。 如果相等把这些数字都存放到数组,进行排序后比较
* 两组数字,如果相等那么输出这个数就是要找的数字;
*/
了解下这个英文参考:吸血鬼数字
An important theoretical result found by Pete Hartley:
If x·y is a vampire number then x·y == x+y (mod 9)
Proof:
Let mod be the binary modulo operator and d(x) the sum of the decimal digits of x.
It is well-known that d(x) mod 9 = x mod 9, for all x.
Assume x·y is a vampire. Then it contains the same digits as x and y, and in particular d(x·y) = d(x)+d(y). This leads to:
(x·y) mod 9 = d(x·y) mod 9 = (d(x)+d(y)) mod 9 = (d(x) mod 9 + d(y) mod 9) mod 9
= (x mod 9 + y mod 9) mod 9 = (x+y) mod 9
The solutions to the congruence are (x mod 9, y mod 9) in {(0,0), (2,2), (3,6), (5,8), (6,3), (8,5)}
Only these cases (6 out of 81) have to be tested in a vampire search based on testing x·y for different values of x and y.
下面五中方法, 其中还是ThinkinJava给出的参考答案效率最高, 其他高效率做法 , 请网友高手大神补充
- import java.util.Arrays;
- public class Demo3 {
- static int a; //千位
- static int b; //百位
- static int c; //十位
- static int d; //个位
- static int a1; //十位
- static int b1; //个位
- static int c1; //十位
- static int d1; //个位
- static int sum = 0; //总和
- static int sum2 = 0; //两数之积
- public static void main(String[] args) {
- long startTime = System.nanoTime();
- method1();
- long endTime = System.nanoTime();
- System.out.println(”method1 :” + (endTime - startTime)); //method1 :185671841
- long s = System.nanoTime();
- method2();
- long d = System.nanoTime();
- System.out.println(”method2 :” + (d - s)); //method2 :90556063
- long s3 = System.nanoTime();
- method3();
- long d3 = System.nanoTime();
- System.out.println(”method3 :” + (d3 - s3));//method3 :574735
- long s4 = System.nanoTime();
- method4();
- long d4 = System.nanoTime();
- System.out.println(”method4 :” + (d4 - s4));//method4 :22733469
- long s5 = System.nanoTime();
- method5();
- long d5 = System.nanoTime();
- System.out.println(”method5 :” + (d5 - s5));//method4 :19871660
- }
- private static void method5() {
- new VampireNumbers(); //该方法 有重复数字
- }
- static class VampireNumbers {
- static int a(int i) {
- return i / 1000;
- }
- static int b(int i) {
- return (i % 1000) / 100;
- }
- static int c(int i) {
- return ((i % 1000) % 100) / 10;
- }
- static int d(int i) {
- return ((i % 1000) % 100) % 10;
- }
- static int com(int i, int j) {
- return (i * 10) + j;
- }
- static void productTest(int i, int m, int n) {
- if (m * n == i)
- System.out.println(i + ” = ” + m + “ * ” + n);
- }
- public VampireNumbers() {
- for (int i = 1001; i < 9999; i++) {
- productTest(i, com(a(i), b(i)), com(c(i), d(i)));
- productTest(i, com(a(i), b(i)), com(d(i), c(i)));
- productTest(i, com(a(i), c(i)), com(b(i), d(i)));
- productTest(i, com(a(i), c(i)), com(d(i), b(i)));
- productTest(i, com(a(i), d(i)), com(b(i), c(i)));
- productTest(i, com(a(i), d(i)), com(c(i), b(i)));
- productTest(i, com(b(i), a(i)), com(c(i), d(i)));
- productTest(i, com(b(i), a(i)), com(d(i), c(i)));
- productTest(i, com(b(i), c(i)), com(d(i), a(i)));
- productTest(i, com(b(i), d(i)), com(c(i), a(i)));
- productTest(i, com(c(i), a(i)), com(d(i), b(i)));
- productTest(i, com(c(i), b(i)), com(d(i), a(i)));
- }
- }
- }
- private static void method4() { // 改进
- for (int i = 11; i < 100; i++) {
- for (int j = i; j < 100; j++) {
- int k = i * j;
- String kStr = Integer.toString(k);
- String checkStr = Integer.toString(i) + Integer.toString(j);
- if (kStr.length() != 4)
- continue;
- char[] kChar = kStr.toCharArray();
- char[] checkChar = checkStr.toCharArray();
- Arrays.sort(kChar);
- Arrays.sort(checkChar);
- boolean isVampire = Arrays.equals(kChar, checkChar);
- if (isVampire) {
- System.out.println(i + ” * ” + j + “ = ” + k);
- }
- }
- }
- }
- private static void method3() { // 官方参考答案
- int[] startDigit = new int[4];
- int[] productDigit = new int[4];
- for (int num1 = 10; num1 <= 99; num1++)
- for (int num2 = num1; num2 <= 99; num2++) {
- // Pete Hartley’s theoretical result:
- // If x·y is a vampire number then
- // x·y == x+y (mod 9)
- if ((num1 * num2) % 9 != (num1 + num2) % 9)
- continue;
- int product = num1 * num2;
- startDigit[0] = num1 / 10;
- startDigit[1] = num1 % 10;
- startDigit[2] = num2 / 10;
- startDigit[3] = num2 % 10;
- productDigit[0] = product / 1000;
- productDigit[1] = (product % 1000) / 100;
- productDigit[2] = product % 1000 % 100 / 10;
- productDigit[3] = product % 1000 % 100 % 10;
- int count = 0;
- for (int x = 0; x < 4; x++)
- for (int y = 0; y < 4; y++) {
- if (productDigit[x] == startDigit[y]) {
- count++;
- productDigit[x] = -1;
- startDigit[y] = -2;
- if (count == 4)
- System.out.println(num1 + ” * ” + num2 + “ : ”
- + product);
- }
- }
- } /*
- * Output: 15 * 93 : 1395 21 * 60 : 1260 21 * 87 : 1827 27 * 81 :
- * 2187 30 * 51 : 1530 35 * 41 : 1435 80 * 86 : 6880
- *///:~
- }
- private static void method2() { // 穷举2
- //遍历四位数,排除00 从1001开始
- for (int i = 1001; i <= 9999; i++) {
- //排除00
- if (i % 100 != 00) {
- for (int k = 0; k < 100; k += 10) {
- if (k != 0) {
- //10 -99
- for (int j2 = 0; j2 <= 9; j2++) {
- //生成第一个两位数
- for (int j = 0; j < 100; j += 10) {
- for (int j3 = 0; j3 <= 9; j3++) {
- //生成第二个两位数
- //判断两数之积
- if ((k + j2) * (j + j3) == i) {
- if (compare2(i, k / 10, j2, j / 10, j3)) {
- System.out
- .println(i + ”=” + (k + j2)
- + ”*” + (j + j3));
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- public static void method1() { //穷举1
- int x = 0, y = 0;
- for (int i = 1; i <= 9; i++) {
- a = i * 1000;
- for (int j = 0; j <= 9; j++) {
- b = j * 100;
- for (int j2 = 0; j2 < 10; j2++) {
- c = j2 * 10;
- for (int k = 0; k < 10; k++) {
- d = k;
- sum = a + b + c + d;
- //取其中四个数字 中组成两个两位数 ,如果这两个两位数之积 等于 sum ,则输入 这个数
- for (int k2 = 1; k2 < 10; k2++) {
- a1 = k2 * 10;
- for (int l = 0; l < 10; l++) {
- if (a1 + b1 > 100) {
- break;
- }
- b1 = l;
- //得到一个两位数字
- for (int l2 = 1; l2 < 10; l2++) {
- c1 = l2 * 10;
- for (int m = l; m < 10; m++) {
- if (c1 + d1 > 100) {
- break;
- }
- d1 = m;
- //再得到一个两位数字
- sum2 = (a1 + b1) * (c1 + d1);
- //计算来两个两位数字之积,如果等于sum
- if (sum2 == sum) {
- //且尾数不能为00
- if (c + d != 0) {
- // 比较这个几个数字 是否一样
- if (compare(a, b, c, d, a1, b1,
- c1, d1)) {
- System.out.println(sum
- + ”=” + (a1 + b1)
- + ”*” + (c1 + d1));
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- private static boolean compare2(int i, int j, int j2, int k, int j3) {
- int a[] = { i % 10, i / 10 % 10, i / 100 % 10, i / 1000 };
- int b[] = { j, j2, k, j3 };
- Arrays.sort(a);
- Arrays.sort(b);
- if (Arrays.equals(a, b))
- return true;
- else
- return false;
- }
- private static boolean compare(int a2, int b2, int c2, int d2, int a12,
- int b12, int c12, int d12) {
- int[] a = new int[4];
- int[] b = new int[4];
- a[0] = a2 / 1000;
- a[1] = b2 / 100;
- a[2] = c2 / 10;
- a[3] = d2;
- b[0] = a12 / 10;
- b[1] = b12;
- b[2] = c12 / 10;
- b[3] = d12;
- Arrays.sort(a);
- Arrays.sort(b);
- if (Arrays.equals(a, b))
- return true;
- else
- return false;
- }
- }
- }
import java.util.Arrays;
public class Demo3 {
static int a; //千位
static int b; //百位
static int c; //十位
static int d; //个位
static int a1; //十位
static int b1; //个位
static int c1; //十位
static int d1; //个位
static int sum = 0; //总和
static int sum2 = 0; //两数之积
public static void main(String[] args) {
long startTime = System.nanoTime();
method1();
long endTime = System.nanoTime();
System.out.println("method1 :" + (endTime - startTime)); //method1 :185671841
long s = System.nanoTime();
method2();
long d = System.nanoTime();
System.out.println("method2 :" + (d - s)); //method2 :90556063
long s3 = System.nanoTime();
method3();
long d3 = System.nanoTime();
System.out.println("method3 :" + (d3 - s3));//method3 :574735
long s4 = System.nanoTime();
method4();
long d4 = System.nanoTime();
System.out.println("method4 :" + (d4 - s4));//method4 :22733469
long s5 = System.nanoTime();
method5();
long d5 = System.nanoTime();
System.out.println("method5 :" + (d5 - s5));//method4 :19871660
}
private static void method5() {
new VampireNumbers(); //该方法 有重复数字
}
static class VampireNumbers {
static int a(int i) {
return i / 1000;
}
static int b(int i) {
return (i % 1000) / 100;
}
static int c(int i) {
return ((i % 1000) % 100) / 10;
}
static int d(int i) {
return ((i % 1000) % 100) % 10;
}
static int com(int i, int j) {
return (i * 10) + j;
}
static void productTest(int i, int m, int n) {
if (m * n == i)
System.out.println(i + " = " + m + " * " + n);
}
public VampireNumbers() {
for (int i = 1001; i < 9999; i++) {
productTest(i, com(a(i), b(i)), com(c(i), d(i)));
productTest(i, com(a(i), b(i)), com(d(i), c(i)));
productTest(i, com(a(i), c(i)), com(b(i), d(i)));
productTest(i, com(a(i), c(i)), com(d(i), b(i)));
productTest(i, com(a(i), d(i)), com(b(i), c(i)));
productTest(i, com(a(i), d(i)), com(c(i), b(i)));
productTest(i, com(b(i), a(i)), com(c(i), d(i)));
productTest(i, com(b(i), a(i)), com(d(i), c(i)));
productTest(i, com(b(i), c(i)), com(d(i), a(i)));
productTest(i, com(b(i), d(i)), com(c(i), a(i)));
productTest(i, com(c(i), a(i)), com(d(i), b(i)));
productTest(i, com(c(i), b(i)), com(d(i), a(i)));
}
}
}
private static void method4() { // 改进
for (int i = 11; i < 100; i++) {
for (int j = i; j < 100; j++) {
int k = i * j;
String kStr = Integer.toString(k);
String checkStr = Integer.toString(i) + Integer.toString(j);
if (kStr.length() != 4)
continue;
char[] kChar = kStr.toCharArray();
char[] checkChar = checkStr.toCharArray();
Arrays.sort(kChar);
Arrays.sort(checkChar);
boolean isVampire = Arrays.equals(kChar, checkChar);
if (isVampire) {
System.out.println(i + " * " + j + " = " + k);
}
}
}
}
private static void method3() { // 官方参考答案
int[] startDigit = new int[4];
int[] productDigit = new int[4];
for (int num1 = 10; num1 <= 99; num1++)
for (int num2 = num1; num2 <= 99; num2++) {
// Pete Hartley's theoretical result:
// If x·y is a vampire number then
// x·y == x+y (mod 9)
if ((num1 * num2) % 9 != (num1 + num2) % 9)
continue;
int product = num1 * num2;
startDigit[0] = num1 / 10;
startDigit[1] = num1 % 10;
startDigit[2] = num2 / 10;
startDigit[3] = num2 % 10;
productDigit[0] = product / 1000;
productDigit[1] = (product % 1000) / 100;
productDigit[2] = product % 1000 % 100 / 10;
productDigit[3] = product % 1000 % 100 % 10;
int count = 0;
for (int x = 0; x < 4; x++)
for (int y = 0; y < 4; y++) {
if (productDigit[x] == startDigit[y]) {
count++;
productDigit[x] = -1;
startDigit[y] = -2;
if (count == 4)
System.out.println(num1 + " * " + num2 + " : "
+ product);
}
}
} /*
* Output: 15 * 93 : 1395 21 * 60 : 1260 21 * 87 : 1827 27 * 81 :
* 2187 30 * 51 : 1530 35 * 41 : 1435 80 * 86 : 6880
*///:~
}
private static void method2() { // 穷举2
//遍历四位数,排除00 从1001开始
for (int i = 1001; i <= 9999; i++) {
//排除00
if (i % 100 != 00) {
for (int k = 0; k < 100; k += 10) {
if (k != 0) {
//10 -99
for (int j2 = 0; j2 <= 9; j2++) {
//生成第一个两位数
for (int j = 0; j < 100; j += 10) {
for (int j3 = 0; j3 <= 9; j3++) {
//生成第二个两位数
//判断两数之积
if ((k + j2) * (j + j3) == i) {
if (compare2(i, k / 10, j2, j / 10, j3)) {
System.out
.println(i + "=" + (k + j2)
+ "*" + (j + j3));
}
}
}
}
}
}
}
}
}
}
public static void method1() { //穷举1
int x = 0, y = 0;
for (int i = 1; i <= 9; i++) {
a = i * 1000;
for (int j = 0; j <= 9; j++) {
b = j * 100;
for (int j2 = 0; j2 < 10; j2++) {
c = j2 * 10;
for (int k = 0; k < 10; k++) {
d = k;
sum = a + b + c + d;
//取其中四个数字 中组成两个两位数 ,如果这两个两位数之积 等于 sum ,则输入 这个数
for (int k2 = 1; k2 < 10; k2++) {
a1 = k2 * 10;
for (int l = 0; l < 10; l++) {
if (a1 + b1 > 100) {
break;
}
b1 = l;
//得到一个两位数字
for (int l2 = 1; l2 < 10; l2++) {
c1 = l2 * 10;
for (int m = l; m < 10; m++) {
if (c1 + d1 > 100) {
break;
}
d1 = m;
//再得到一个两位数字
sum2 = (a1 + b1) * (c1 + d1);
//计算来两个两位数字之积,如果等于sum
if (sum2 == sum) {
//且尾数不能为00
if (c + d != 0) {
// 比较这个几个数字 是否一样
if (compare(a, b, c, d, a1, b1,
c1, d1)) {
System.out.println(sum
+ "=" + (a1 + b1)
+ "*" + (c1 + d1));
}
}
}
}
}
}
}
}
}
}
}
}
private static boolean compare2(int i, int j, int j2, int k, int j3) {
int a[] = { i % 10, i / 10 % 10, i / 100 % 10, i / 1000 };
int b[] = { j, j2, k, j3 };
Arrays.sort(a);
Arrays.sort(b);
if (Arrays.equals(a, b))
return true;
else
return false;
}
private static boolean compare(int a2, int b2, int c2, int d2, int a12,
int b12, int c12, int d12) {
int[] a = new int[4];
int[] b = new int[4];
a[0] = a2 / 1000;
a[1] = b2 / 100;
a[2] = c2 / 10;
a[3] = d2;
b[0] = a12 / 10;
b[1] = b12;
b[2] = c12 / 10;
b[3] = d12;
Arrays.sort(a);
Arrays.sort(b);
if (Arrays.equals(a, b))
return true;
else
return false;
}
}
}