Title: 4-digit vampire number

Recently revisiting java, I decided to read "Java Programming Thoughts", and saw a more interesting question: vampire numbers. Where the reference blog is Vampire Digital

Title
Vampire number refers to a number with an even number of digits, which can be obtained by multiplying a pair of numbers, and each pair of numbers contains half of the digits of the grade, and the numbers selected from the original number can be arranged in any order. Numbers ending with two zeros are not allowed, for example: 1260 = 21 * 60, write a program to find all vampire numbers with 4 digits

analyze

  1. Wrong idea:
    At the beginning, my idea was inspired by the question of LeetCode136: Numbers that only appear once. I observed that in the result of multiplying two two-digit numbers and the final multiplication, each number must appear even times, combined with XOR The characteristic of itself being 0, the brain is hot, and I want to store all 8 numbers (two two-digit numbers + one four-digit number) into an array, and then XOR each element of the array, and the final XOR result is 0 is the vampire number, print it out, and complete the flowering. But a deviation was found during debugging, for example: 4550 = 70 * 65. This pair is obviously not a vampire number, but the final XOR result is 0. The reason is that 5 appears three times, some other numbers appear once, and some appear twice, and the result may still be 0. This plan passes
  2. Correct idea:
    Assuming two numbers are i and j, the product is result = i × j.
    Note 1 : We all know that two layers of for loops must be used, so there will be a problem of repetition. In order to avoid repetition, assume j > i (in fact, it can also be assumed that i > j, the result is the same). As long as j starts counting from i, there will be no embarrassing situation similar to 21 × 60 and 60 × 21 appearing together.
    Pay attention to point 2 : Since i and j both have two digits, the result must be four digits, so i × j > 1000, that is, j > 1000 / i, take j = 1000 / i + 1, in addition, to the second half of the loop The situation that i > 1000 / i + 1 may appear in the segment, combined with attention point 1, it is not difficult to draw a conclusion: the initial value of j in the second cycle should be 1000 / i + 1 and the larger value of i Note point
    3 : The most critical point, assuming result = 1000a + 100b + 10c + d, then i = 10a + b, j = 10c + d (a, b, c, and d in i and j can be in any position, such as i=10d + a, j = 10b + c, but according to the definition of vampire number, it must contain the four letters a, b, c, d), we draw a conclusion: result - i - j = 990a + 99b = 9( 110a + 11b), so the 4-digit vampire number has a property: it can be divisible by 9! According to this point, most of the numbers that do not meet the conditions can be deleted.
    Note 4 : You can store two two-digit numbers into an array Num_Array, and store the product into an array: Result_Array, then sort the values ​​of the two arrays, and call the static method equals in the Arrays class to compare the two arrays after sorting Are the values ​​inside consistent. The same conclusion can be drawn: the number of vampires has been found

code:

public class VampireNum {
    
    
    public static void main(String[] args) {
    
    
         char[] Num_Array = new char[4];          // 存储的是两个相乘的的二位数
         char[] Result_Array = new char[4];       // 存储相乘后的结果

        for (int i = 10; i < 100; i++){
    
    
            for (int j = 1000/i+1 > i ? 1000/i+1 : i; j < 100; j++) {
    
       // 由于i * j > 1000, 假设j > i,则j必须从i或者1000/i+1中的较大的开始
                int result = i * j;
                if (result % 100 == 0 || (result - i - j) % 9 != 0 || result / 1000 > 9)     // 公式推导的结果
                    continue;
                Num_Array = (String.valueOf(i) + String.valueOf(j)).toCharArray();
                Result_Array = String.valueOf(result).toCharArray();
                Arrays.sort(Num_Array);
                Arrays.sort(Result_Array);
                if (Arrays.equals(Num_Array, Result_Array)) {
    
    
                    System.out.println(i + " * " + j + " = " + result);
                }
            }
        }
    }
}

Running result :

15 * 93 = 1395
21 * 60 = 1260
21 * 87 = 1827
27 * 81 = 2187
30 * 51 = 1530
35 * 41 = 1435
80 * 86 = 6880

Extra :

The source code of "Java Programming Thoughts" is similar to the above points of attention, but there are fewer steps for j to choose between 1000/i+1 and i, and more cycles.
In addition, (num1 * num2) % 9 != (num1 + num2) % 9 in the source code is the same as Note 3, both of which indicate that the number of vampires can be divisible by 9 (after transposition, it is consistent with the above conclusion)

public class E10_Vampire {
    
    
    public static void main(String[] args) {
    
    
        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);
                        }
                    }
            }
    }

}

Guess you like

Origin blog.csdn.net/qq_43419761/article/details/113267566