CSP 201312-4 Interesting Number Java

The title gives three important conditions:

  1. Its numbers only contain 0, 1, 2, 3, and these four numbers have appeared at least once.
  2. All 0s appear before all 1s, and all 2s appear before all 3s.
  3. The highest digit is not 0.

According to these three conditions, we can draw a conclusion:
4. The highest digit can only be 2
This is because the highest digit cannot be 1, because all 0s must be in front of 1. Similarly, it cannot be 3, so it can only be 2.
And, the limit is only between 01 and 23

Statistical programs are generally discussed according to different situations, that is, to classify various situations.

enumerate

analysis

Step by step analysis, the highest bit must be 2, then look at the n-1 bit
Insert picture description here

According to the requirements of the question, each number must appear, so 01 appears at least 2 times, and the maximum appears n-2 times.
Assuming that 01 occupies a total of k digits, then select from n-1, and the value of k is 2<=k<=n-2
Insert picture description here
to continue exploring 01. After the digits of 01 are selected, look at the arrangement of 01, because All 0s must be in front of 1, so the k digits occupied by 01 must be 0 on the left and 1 on the right.
Insert picture description here
Set the number of 0s to t, then the number of 1s is kt.
Since 01 appears at least once , Then the value of t is 1<=t<=k-1, so the permutation of 01 is k-1.
Similarly, the permutation of 23 is nk-1.
Therefore, when a value of k is determined, There are so many answers below
Insert picture description here

And the range of k value has been analyzed before, so the answer to this question is

for (int k = 2; k <= n - 2; k++) {
    
    
	//C[n - 1][k]表示n-1个数位中取出k个位数的方法数
	res += (k - 1) * (n - k - 1) * C[n - 1][k];
}

As the amount of data is relatively large, remember to take the surplus in relevant places.

Problem-solving code

import java.util.*;

public class Main{
    
    
    public static void main(String[] args) {
    
    
        Scanner input = new Scanner(System.in);
        
        int n = input.nextInt();
        int MOD = (int)(1e9 + 7);
        int[][] C = new int[n][n];
        //这里是求组合数的一个小算法
        for (int i = 0; i < n; i ++) {
    
    
            for (int j = 0; j <= i; j ++) {
    
    
               if (j == 0) {
    
    
                   C[i][j] = 1;
               } else {
    
    
                   C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MOD;
               }
            }
        }
        
        //此处为了方便我直接使用了长整型
        long res = 0;
        for (long k = 2; k <= n - 2; k ++) {
    
    
            res = (res + (k - 1) * (n - k - 1) * C[n - 1][(int)k]) % MOD;
        }
        
        System.out.println(res);
        
        input.close();
    }
}

State transition --> dynamic programming

Analyze the possible states of each digit. In this case, each state must meet the requirements of the question.
Then, starting from the highest to the lowest position, the analysis should have the following states:


 - 只用了2, 没有用0,1,3
 - 只用了2、0,没有用1,3
 - 只用了2、3,没有用0、1
 - 只用了2、0、1,没有用3
 - 只用了2、0、3,没有用1
 - 全都用了

There are only the above six states. As for the similar use of 2, 1 and no 0, 3, this state does not exist, because 0 must be in front of 1, and there will definitely be 0 if there is 1.

Assuming the above six state flags, state 0 to state 5,
assuming i is the i-th digit from high to low, the state relationship can be deduced:

s[i][0] = 1

s[i][1] = s[i - 1][0] + s[i - 1][1] * 2

s[i][2] = s[i - 1][0] + s[i - 1][2]

s[i][3] = s[i - 1][1] + s[i - 1][3] * 2

s[i][4] = s[i - 1][1] + s[i - 1][2] + s[i - 1][4] * 2

s[i][5] = s[i - 1][3] + s[i - 1][4] + s[i - 1][5] * 2

You can try to sort it out by yourself, take n as an example of 6, from high to low, the number of states corresponding to:
Insert picture description here
deduce the relationship, it is easy to write code

Problem-solving code

import java.util.*;

public class Main{
    
    
    public static void main(String[] args) {
    
    
        Scanner input = new Scanner(System.in);
        
        int MOD = (int)(1e9 + 7);
        int n = input.nextInt();
        long[][] s = new long[n + 1][6];
        
        //此处我并没有详细处理是否溢出的问题
        for (int i = 1; i <= n; i++) {
    
    
            s[i][0] = 1;
            s[i][1] = (s[i - 1][0] + s[i - 1][1] * 2) % MOD;
            s[i][2] = (s[i - 1][0] + s[i - 1][2]) % MOD;
            s[i][3] = (s[i - 1][1] + s[i - 1][3] * 2) % MOD;
            s[i][4] = (s[i - 1][1] + s[i - 1][2] + s[i - 1][4] * 2) % MOD;
            s[i][5] = (s[i - 1][3] + s[i - 1][4] + s[i - 1][5] * 2) % MOD;
        }
        
        System.out.println(s[n][5]);
        
        input.close();
    }
}

Guess you like

Origin blog.csdn.net/qq_43349112/article/details/113963802