CFgym102394I - Interesting Permutation

题目

DreamGrid has an interesting permutation of \(1,2,...,n\) denoted by \(a_1,a_2,...a_n\).

  • For each \(1 \le i \le n\), \(f_i = \max\{a_1,a_2...,a_i\}\).
  • For each \(1 \le i \le n\), \(g_i = \min\{a_1,a_2...,a_i\}\).
  • For each \(1 \le i \le n\), \(h_i = f_i - g_i\).

Given the sequence h, please calculate the number of different permutations that can generate the sequence h. Print the answer modulo \(10^9+7\).

思路

一开始想歪想复杂了。\(h_i\)代表最大值和最小值之间的差值,这个差值代表可以选择的数字数。维护一个可选数字数cnt。当\(h_i > h_{i-1}\),说明当前位是前缀的最大值或最小值,所以\(ans=2\times ans\)\(cnt = cnt + (h_i - h_{i-1} - 1)\);当\(h_i == h_{i-1}\),说明当前位置可以选一个数字放进去,所以\(ans=cnt\times ans\)\(cnt = cnt - 1\)

一开始特判一些不合法的情况,然后就可以求解了。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
typedef long long ll;
const int M = 1e9 +7;
#define endl '\n'
int h[N];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while(t--) {
        int n;
        cin >> n;
        bool ok = true;
        for(int i = 1; i <= n; i++) {
                cin >> h[i];
                if(i > 1 && h[i] < h[i - 1] || h[i] >= n) ok = false;
        }

        if(h[1] != 0) ok = false;
        else if(h[n] != n - 1) ok = false;
        else if(n > 1 && h[2] == 0) ok = false;

        if(!ok) cout << 0 << endl;
        else {
            int cnt = 0;
            ll ans = 1;
            for(int i = 2; i <= n; i++) {
                if(h[i] > h[i - 1]) {
                    cnt += h[i] - h[i - 1] - 1;
                    ans = ans * 2 % M;
                } else {
                    ans = ans * cnt % M;
                    cnt--;
                }
            }
            cout << ans << endl;
        }
    }
}

posted @ 2021-05-21 10:53  limil  阅读(35)  评论(0编辑  收藏  举报