Gym 102394 I. Interesting Permutation(DP)

Link

Title:

Given a number n, and then there is a sequence of length n, the value of the ith item of this sequence is the result of subtracting the minimum value from the maximum value of the first i item of a certain sequence. How many sequences of length n can be constructed.

analyze:

First let's consider a scenario that must have no answer:

  • If the beginning is not 0, or the end is not n-1 there must be no answer
  • There must be no answer if the entire sequence is not monotonically increasing
  • If the difference is less than the sequence length -1, there must be no answer (the length is x, and the number of x with the smallest difference is 1, 2...x, so the difference is x-1, so the difference will not be less than the sequence length -1)

Then we analyze: we just got this problem and don't know how to solve it, then we have to find a breakthrough, the last (n-1) place of this breakthrough,

We see that when n-1 appears, there is no doubt that (1 or n) must be placed in the position.

Then we have two ways to put this position (assuming that 1 is placed), then the one that is equal to (n-1) is empty first and counts num empty,

Looking forward, if the previous number is (n-2), then we can definitely put (2 or n) so that the satisfied difference is (n-2), (assuming we put 2)

Then the same as above, looking forward if the previous number is (n-4), then we think that the number (4 or n) that can be placed in this position If 4 is placed, but we still have 3, he must be in this position Put it later, then use the num spaces we recorded earlier, just choose one of the num spaces and put 4. (In the same way, put n and put 3 in the air).

Then we get:

int _;
    scanf("%d", &_);
    while (_--)
    {
    
    
        scanf("%lld", &n);
        ll flag = 1;
        for(int i = 1; i <= n; i++)
        {
    
    
            scanf("%lld", &a[i]);
            if(i == 1)
            {
    
    
                if(a[i] != 0) flag = 0;///不是0开头一定没有答案
            }
            else
            {
    
    
                if(a[i] < a[i - 1]) flag = 0;///不单调递增 一定没有答案
                if(a[i] < i - 1) flag = 0;///这个是差值小于数量一定没有答案
            }
        }

        if(a[n] != n - 1) flag = 0;//最终差值不为n-1一定没有答案
        if(flag == 0) puts("0");//没有答案输出0
        else
        {
    
    
            ll ans = 1;
            ll num = 0;
            for(int i = n; i > 1; i--)
            {
    
    
                int j = i;
                while(j > 1 && a[j] == a[i]) j--, num++;/// 相同的数量
                num--;
                for(int k = 1; k <= a[i] - a[j] - 1; k++)
                {
    
    
                    ans = ans * num  % MOD;/// 选取最小的数 有num位置可以选择
                    num--;
                }            
                ans = ans * 2 % MOD;/// 两种选择
                i = j + 1;///转移到与其不同的敌方。
            }
            printf("%lld\n", ans);
        }
    }

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326263729&siteId=291194637