#include #define X first #define Y second #define ll long long #define INF (ll)(1e9 + 7) #define rep(i, x, n) for (int i = x; i < n; i++) #define rev(A) reverse((A).begin(), (A).end()) #define sorv(A) sort((A).begin(), (A).end()) #define pb push_back #define ios ios::sync_with_stdio(false) #define db(...) ZZ(#__VA_ARGS__, __VA_ARGS__) #define dbv(v) cout << "Printing "#v << " --> \n"; for(int i=0;i \n"; for(auto i=st.begin();i!=st.end();i++) cout << *i << " "; cout << "\n"; #define dbmp(mp) cout << "Printing "#mp << " --> \n"; for(auto i=mp.begin();i!=mp.end();i++) cout << #mp"[" << i->first << "]"<< " = " << i->second << "\n"; template void ZZ(const char* name, Arg1&& arg1){std::cout << name << " = " << arg1 << std::endl;} template void ZZ(const char* names, Arg1&& arg1, Args&&... args) { const char* comma = strchr(names + 1, ','); std::cout.write(names, comma - names) << " = " << arg1; ZZ(comma, args...); } using namespace std; ll t, n, q; ll ans = 1; ll factorials[1242]; ll C[1300]; ll nCrModpDP(ll n, ll r, ll p) { p = INF; memset(C, 0, sizeof(C)); C[0] = 1; // Top row of Pascal Triangle for (ll i = 1; i <= n; i++) { // Fill entries of current row using previous // row values for (ll j = min(i, r); j > 0; j--) // nCj = (n-1)Cj + (n-1)C(j-1); C[j] = (C[j] + C[j-1])%p; } return C[r]; } ll nCr(ll N, ll R) { ll p = INF; if (R == 0) return 1; ll ni = N % p, ri = R % p; return (nCr(N/p, R/p) * nCrModpDP(ni, ri, p)) % p; } ll nPr(ll N, ll R) { return (factorials[R] * nCr(N, R)) % INF; } void find_factorials() { factorials[0] = 1; for (ll i = 1; i <= n; i++) { factorials[i] = (factorials[i - 1] * i) % INF; } } void calc (ll* columns) { for (ll i = 1; columns[i] > 1; i++) { ans = (ans * factorials[columns[i]]) % INF; } } void arrange(ll rows, ll current) { if (rows >= current) { ans = (ans * nPr(rows, current)) % INF; return; } for (ll i = 1; i <= rows; i++) { ll columns[current + 1]; ll elements = i; columns[1] = i; ll j; for (j = 2; elements > 0; j++) { columns[j] = 1; elements--; } ll last_column = j - 1; j = last_column; calc(columns); while(columns[j - 1] != i) { ll k = 2; while (k + 1 <= j) { columns[k]++; columns[j]--; k++; if (columns[j] == 0) { j--; } calc(columns); } } } } int main() { ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n; find_factorials(); ll ar[n]; for (ll i = 0; i < n; i++) { cin >> ar[i]; } int inv[n + 1] = {0}; for (ll i = 1; i < n; i++) { if (ar[i] < ar[i - 1]) { inv[i] = 'y'; } } inv[n] = 'e' + 'n' + 'd'; ll rows = 1; for (ll i = 0; i < n; i++) { if (inv[i + 1] == 'y') { rows = i + 1; break; } else if (inv[i + 1] == 'e' + 'n' + 'd') { ans = ((nPr(i + 1, i + 1)) % INF) - i; break; } } ll current = 0; for (ll i = rows; i < n; i++) { current++; if (inv[i + 1] == 'y') { while (current >= rows) { current -= rows; ans = (ans * factorials[rows]) % INF; } if (current > 0) { rows = current; ans = (ans * factorials[rows]) % INF; } } else if (inv[i + 1] == 'e' + 'n' + 'd') { arrange(rows, current); break; } } cout << ans << endl; return 0; }