Factorial sum (binary enumeration, dfs enumeration)

Posted by PhilVaz on Tue, 08 Feb 2022 18:14:41 +0100

3481. Sum of factorials

Question Restatement:

Given a non negative integer n, please judge whether there are some integers Xi, which can make n = ∑ 1 ≤ i ≤ txi!, Where t ≥ 1,xi ≥ 0, xi = XJ, IFF i = J.

iff means if and only if.

Input format

The input contains multiple sets of test data.

Each group of data occupies one row and contains a non negative integer n.

The last line is a negative number, indicating the end of input and no processing is required.

Output format

Output a row of results for each group of data. If n can be expressed as the sum of factorials of several numbers, output YES, otherwise output NO.

Data range

0≤n≤106,
Each set of input contains up to 100 sets of data.

Input sample:

9
-1

Output example:

YES

Problem analysis:

This problem requires giving an integer. Let's judge whether the sum of the factorials of some numbers is exactly equal to this integer. Under the given conditions of the problem, the integer range of 0 ≤ n ≤ 10 ^ 6,9 factorial equal to 362800 can meet this range, so we can convert this problem into a given integer, Can we find several numbers in the factorial of 09 and make their sum equal to this integer? We can enumerate all the sums of the factorial of 09 and compare the given integer to get the result

Solution:

Binary enumeration, dfs enumeration

Problem solving:

Binary code and dfs code are in it:
package cn.basic.algorithm;
import java.util.HashSet;
import java.util.Scanner;

/**
 * Given a non negative integer n, please judge whether there are some integers Xi, which can make n = ∑ 1 ≤ i ≤ txi!, Where t ≥ 1,xi ≥ 0, xi = XJ, IFF i = J.
 *
 * iff Indicates if and only if.
 *
 * Input format
 * The input contains multiple sets of test data.
 *
 * Each group of data occupies one row and contains a non negative integer n.
 *
 * The last line is a negative number, indicating the end of input and no processing is required.
 *
 * Output format
 * Output a row of results for each group of data. If n can be expressed as the sum of factorials of several numbers, output YES, otherwise output NO.
 *
 * Data range
 * 0≤n≤106,
 * Each group contains up to 100 input groups of data.
 *
 * Input sample:
 * 9
 * -1
 * Output example:
 * YES
 */
public class Main7 {
    // Create a factorial array
    public static int[] arrays = new int[10];
    public static int n;
    public static HashSet<Integer> set = new HashSet<>();
    public static void main(String[] args) {
        // Initialize factorial array
        arrays[0] = arrays[1] = 1;//The factorial of 0 is 1
        for (int i = 2; i < 10; i++) {
            arrays[i] = i * arrays[i-1];
        }
        //dfs enumeration method
        //dfs(0,0,arrays);
        //Binary enumeration method
        for (int i = 0; i<1024; i++) {//I < 1024 can also be written as I < 1 < < 10, which has the same meaning
            int sum = 0;
            for (int j = 0; j < 10; j++) {
            //You need to know that when num > > J & 1 = = 1, the j-th bit on the binary number corresponding to num is 1
                if ((i>>j&1) == 1){
                    sum += arrays[j];
                }
            }
            //Note that 0 cannot be added to the set set because t > = 1
            if (sum !=0){set.add(sum);}

        }
        Scanner scanner = new Scanner(System.in);
        while (true){
            n = scanner.nextInt();
            // If you encounter 1, exit
            if (n < 0){
                break;
            }
            if (set.contains(n)){
                System.out.println("YES");
            }else {
                System.out.println("NO");
            }


        }
    }
    public static void dfs(int sum,int n,int[]c){
        if (sum > 0){
            set.add(sum);
        }
        for (int i = n;i < 10; i++) {
            sum += c[i];
            dfs(sum,i+1,c);
            sum -=c[i];
        }
    }
}

Code analysis:

First, create a factorial array, store the factorials of 0 ~ 9 in turn, use the factorial array for combination, and add it to the HashSet set (de duplication) to judge the input n. Factorial arrays can be combined in two ways: binary and dfs enumeration.

Binary mode: the length of our factorial array is 10. If the value is, the corresponding binary bit will be 1 and not 0. Then there are 2 ^ 10, that is, 1024 possibilities. 0000000000 means none of them (because t > = 1 needs to eliminate this possibility), and 1111111 means all of them. Then find the factorial sum of these 1024 possibilities and add them to the HashSet set. At this time, we need to know which of the ten numbers are selected. When the value of op > > J & 1 is 1, it means that the number on the j-th bit under the binary of op is 1. We judge which numbers are optional according to this. 1024 numbers are calculated in turn, and the 10 binary digits of each number are traversed once, If it is 1, sum the addition and add the result to the set. After calculation, set the sum to 0 and start to calculate the next number. It should be noted that if it is all 0, it may not be added to the set.

dfs method: every time the method starts to judge the condition, if the sum is greater than 0, it will be added to the set, in which there will be repeated additions, but the set can be de duplicated. Start the cycle from the current node, update the sum, enter the next node and perform recursion. Whenever a method ends, we need to subtract the factorial value currently added. We can get all possible combinations in this way. This enumeration method has high time complexity and is easy to timeout. It is not recommended to use this method.

Binary enumeration summary:

It is generally applicable to the problem that there are only two possibilities: taking and not taking. List each possibility. If taking, make the corresponding binary bit 1, otherwise make the corresponding binary bit 0. We need to judge each bit of the corresponding binary of a certain number. Through this judgment, we can know whether to take the corresponding number on this bit. The judgment method: when the value of op > > J & 1 is 1, Indicates that the number on the j-th bit under the binary of op is 1

// There are n binary enumeration templates that can be selected
for (int i = 0; i<1<<n; i++) {//I < 1024 can also be written as I < 1 < < 10, which has the same meaning
            for (int j = 0; j < n; j++) {
            //You need to know that when num > > J & 1 = = 1, the j-th bit on the binary number corresponding to num is 1
                if ((i>>j&1) == 1){
                    //Corresponding to the digit 1 on the binary bit, processing is carried out, such as summation
                }
            }
        }

Topics: Java Algorithm