Java 找出四位数的全部吸血鬼数字 基础代码实例

/**

* 找出四位数的全部吸血鬼数字

* 吸血鬼数字是指位数为偶数的数字,能够由一对数字相乘而得到,而这对数字各包括乘积的一半位数的数字,当中从最初的数字中选取的数字能够随意排序.

* 以两个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;
    }
}
}

Java 找出四位数的全部吸血鬼数字 基础代码实例

时间: 2024-08-09 21:59:54

Java 找出四位数的全部吸血鬼数字 基础代码实例的相关文章

c语言:找出1到4000中,数字的各位数之和能被4整除的数有多少个?

找出1到4000中,数字的各位数之和能被4整除的数,如:745:7+4+5=16,16可以被4整除:28:2+8=10,10不能被4整除:745就是这样的特殊数字,而28不是,求:这样的数字共有多少个? 解: (1)对于4000,4+0+0+0=4,显然4000是满足条件的数字: (2)对于1到3999,我们把每个数字看成4位[][][][]的形式,第一位[]取0到3,后3位取[0][0][0]到[9][9][9],用sum表示4位数字的和: 2.1:若后3位为一个奇数,则第1位取1或3,必定可

找出区间[A, B]内所有数字的奇数字位出现次数为偶数,偶数字位出现次数为计数的数的个数。(数位DP)

题目:找出区间[A, B]内所有数字的奇数字位出现次数为偶数,偶数字位出现次数为计数的数的个数. 分析:这道题的状态同样不好取,因为要求每一个奇数的个数都要为偶数,每一个偶数的位数都要为奇数,又因为只有10个数(0~9),又因为没个数只有3种状态,分别是没有(0),奇数个(1),偶数个(2),这样我们就利用3进制进行压缩就可以了,3的10次方不超过60000,因此直接开60000即可,这样dp[i][j]的i表示当前处理到了第i为,j表示当前(0~9)对应的状态 #include <cmath>

log(n)时间内找出数组第i小的数字

参考算法导论9.2 R_Select(int *a,int p,int r,int i){ if(p==r) return a[p]; int q=partition(a,p,r); int k=q-p; if(i==k) return a[q]; else if(i<k) return R_Select(a,p,q-1,i); else return R_Select(a,q+1,r,i-k); } log(n)时间内找出数组第i小的数字

关于JAVA中事件分发和监听机制实现的代码实例-绝对原创实用

http://blog.csdn.net/5iasp/article/details/37054171 文章标题:关于JAVA中事件分发和监听机制实现的代码实例 文章地址: http://blog.csdn.net/5iasp/article/details/37054171 作者: javaboy2012Email:[email protected]qq:    1046011462 一.场景假设 假设有博客系统中需要实现如下功能: 系统中用户发布文章,修改文章,删除文章时,需要一些相关的操作

java:找出占用CPU资源最多的那个线程(HOW TO)

在这里对linux下.sun(oracle) JDK的线程资源占用问题的查找步骤做一个小结:linux环境下,当发现java进程占用CPU资源很高,且又要想更进一步查出哪一个java线程占用了CPU资源时,按照以下步骤进行查找: 先用top命令找出占用资源厉害的java进程id,如: 如上图所示,java的进程id为'12377',接下来用top命令单独对这个进程中的所有线程作监视: ? 1 top -p 12377 -H 如图: 如上图所示,linux下,所有的java内部线程,其实都对应了一

Java找出一组数字的最大值

形如:int [] nums = {7,2,8,9,1,12}; 解一:两两比较并记录下标,下次比较拿上次比较的最大值和上次比较的下一个进行比较,循环一次找出最大值 1 /** 2 * @author 马向峰 比较一遍找出最大值 3 * @param arr 4 * @return 5 */ 6 private static int getMaxNum(int[] arr) { 7 8 // 记录下标 9 int index = 0; 10 // 假设第一个为最大值 11 int max = a

JVM调优之jstack找出最耗cpu的线程并定位代码

一.jstack使用总结 分析java进程,cpu占用高的问题 { 1.找到cpu占用高的进程pid 在top中,按组合键: shift + h ,会按cpu使用从高到低排序2.找到cpu占用高的线程pid top -Hp cpu高的进程pid, shift +h 查找最高线程,显示线程3.jstack 进程的pid | grep -A 线程pid的十六进制 #分析Java应用程序线程堆栈dump出来 printf "%x\n" cpu高的线程pid ==> 得到十六进制 pyt

Java编写一个四位数的随机验证码

import java.util.Random; /* 随机数类 Random 需求: 编写一个函数随机产生四位的验证码.  */ public class Demo5 { public static void main(String[] args) { /* Random random = new Random(); int randomNum = random.nextInt(10)+1; //产生 的 随机数就是0-10之间 System.out.println("随机数:"+ 

[java] 找出字符串中出现最多的字符和出现的次数

逛园子看到一童鞋做的华为上机题目,写来好长的代码,懒得看,感觉不可能这么难,于是动手敲了下. import java.util.Scanner; public class StringTest { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Scanner scanner = new Scanner(System.in); String A = s