Exchange "UER # 2 'message

Exchange "UER # 2 'message

Geely title ..

Difficult to find a replacement cycle of each is independent, each cycle corresponding to each block of an independent link.

Depending on the nature of the topic, each block Unicom to do something equivalent to it in accordance with the number of small to large to traverse the spanning tree dfs do, we only need to consider a dfs spanning tree can do.

For a dfs spanning tree, the son of each point according to numbers from small to large, consider node \ (u \) and its son \ (v_1, v_2..v_k \) , where \ (v_k \) right eventually the value \ (U \) position, \ (\ FORALL I <K, V_I \) values will first \ (v_ {i + 1} \) position up, to access the \ (v_i + 1 \) time to continue to do the same thing, eventually arriving (v_ {i + 1} \ ) \ on the leftmost subtree tree leaves. Dfs defined inverse order for the first traversal of a large number of sons dfs sequence, this process done the equivalent node \ (v \) to the former node corresponding inverse order of dfs, dfs root node to the inverse order last the corresponding node. The equivalent of doing a replacement in reverse order dfs!

Then only need each cycle corresponding inverse order dfs seek out, and then calculate how many trees there are inverse order dfs compliance. For a matching tree, which even some throwback edge matching can be obtained FIG vigorously to about DP, the complexity of the \ (\ mathcal O (n-^. 3) \) .

code

/*program by mangoyang*/
#include <bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
    int ch = 0, f = 0; x = 0;
    for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
    for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
    if(f) x = -x;
}
const int N = 505, mod = 998244353;
int vis[N], pw[N], a[N], f[N][N], h[N][N], c[N][N], n;
inline void up(int &x, int y){ x = x + y >= mod ? x + y - mod : x + y; }
inline int gao(vector<int> &A){
    if(!(int) A.size()) return 1;
    int m = A.size();
    for(int i = 0; i < m; i++)
        for(int j = i + 1; j < m; j++)
            c[i][j] = c[i][j-1] + (A[j] > A[i]);
    for(int i = 0; i < m; i++)
        for(int j = 0; j < m; j++) f[i][j] = 0;
    for(int i = 0; i < m; i++) f[i][i] = h[i][i] = 1;
    for(int i = m - 1; ~i; i--)
        for(int j = i + 1; j < m; j++){
            f[i][j] = h[i][j] = 1ll * f[i+1][j] * pw[c[i][j]] % mod;
            for(int k = i; k < j; k++) if(A[i] > A[k+1])
                up(f[i][j], 1ll * h[i][k] * f[k+1][j] % mod);
        }
    return f[0][m-1];
}
int main(){
    read(n), pw[0] = 1;
    for(int i = 1; i <= n; i++) read(a[i]);
    for(int i = 1; i <= n; i++) pw[i] = 2ll * pw[i-1] % mod;
    int ans = 1;
    for(int i = 1; i <= n; i++) if(!vis[i]){
        vector<int> A;
        vis[i] = 1;
        for(int p = a[i]; p != i; p = a[p])
            A.push_back(p), vis[p] = 1;
        ans = 1ll * ans * gao(A) % mod; 
    }
    cout << ans << endl;
}

Guess you like

Origin www.cnblogs.com/mangoyang/p/11708256.html