[LOJ # 3042. "ZJOI2019" Mahjong

LOJ # 3042. "ZJOI2019" Mahjong

How to determine a set of cards there is not a subset of Hu Hu

To use a \ (dp [j] [k ] [0/1] \) expressed j consecutive two strings, there are k consecutive one string, there is no pair, then remember what the collection of this brand 2 is equal to the number of colors is greater than a few

We \ (dp [j] [k ] [0/1] \) is greater than the number of colors is equal to 2 as the state of a card, and reference numeral to each state, a do dp

\ (f [i] [j ] [S] \) represents consideration to the second \ (I \) kinds of colors, there are \ (J \) cards, the state label is (S \) \ the number of programs recorded on \ (J \) cards to win the program number is not \ (S (J) \) , it is desirable to \ (\ frac {\ sum_ { j = 13} ^ {\ infty} S (j)} {( 4n- 13)!} \)

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define MAXN 200005
#define ba 47
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        res = res * 10 +c - '0';
        c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
        out(x / 10);
    }
    putchar('0' + x % 10);
}
const int MOD = 998244353;
int inc(int a,int b) {
    return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
    return 1LL * a * b % MOD;
}
void update(int &x,int y) {
    x = inc(x,y);
}
void upmax(int &x,int y) {
    x = max(x,min(4,y));
}
int fpow(int x,int c) {
    int res = 1,t = x;
    while(c) {
        if(c & 1) res = mul(res,t);
        t = mul(t,t);
        c >>= 1;
    }
    return res;
}
int N;
int cnt[105];
struct state {
    int d[3][3];
    state() {memset(d,-1,sizeof(d));}
    friend state trans(const state &a,int t) {
        state c;
        for(int j = 0 ; j <= 2 ; ++j) {
            for(int k = 0 ; k <= 2 ; ++k) {
                if(a.d[j][k] == -1) continue;
                for(int i = 0 ; i <= min(2,t - j - k) ; ++i) {
                    upmax(c.d[k][i],a.d[j][k] + j + (t - j - k - i) / 3);
                }
            }
        }
        return c;
    }
    friend state Max(const state &a,const state &b) {
        state t;
        for(int j = 0 ; j <= 2 ; ++j) {
            for(int k = 0 ; k <= 2 ; ++k) {
                t.d[j][k] = max(a.d[j][k],b.d[j][k]);
            }
        }
        return t;
    }
    friend bool operator == (const state &a,const state &b) {
        for(int j = 0 ; j <= 2 ; ++j) {
            for(int k = 0 ; k <= 2 ; ++k) {
                if(a.d[j][k] != b.d[j][k]) return false;
            }
        }
        return true;
    }
    friend bool operator != (const state &a,const state &b) {
        return !(a == b);
    }
    friend bool operator < (const state &a,const state &b) {
        for(int j = 0 ; j <= 2 ; ++j) {
            for(int k = 0 ; k <= 2 ; ++k) {
                if(a.d[j][k] != b.d[j][k]) return a.d[j][k] < b.d[j][k];
            }
        }
        return false;
    }
};
struct MJ {
    state dp[2];int cnt;
    MJ() {cnt = 0;dp[0].d[0][0] = 0;}
    friend MJ Trans(const MJ &a,int t) {
        MJ c;
        c.dp[1] = trans(a.dp[1],t);
        if(t >= 2) c.dp[1] = Max(trans(a.dp[0],t - 2),c.dp[1]);
        c.dp[0] = trans(a.dp[0],t);
        if(t >= 2) c.cnt = min(a.cnt + 1,7);
        else c.cnt = a.cnt;
        return c;
    }
    friend bool operator == (const MJ &a,const MJ &b) {
        for(int i = 0 ; i < 2 ; ++i) if(a.dp[i] != b.dp[i]) return false;
        if(a.cnt != b.cnt) return false;
        return true;
    }
    friend bool operator < (const MJ &a,const MJ &b) {
        for(int i = 0 ; i < 2 ; ++i) if(a.dp[i] != b.dp[i]) return a.dp[i] < b.dp[i];
        if(a.cnt != b.cnt) return a.cnt < b.cnt;
        return false;
    }
    bool win() {
        if(cnt >= 7) return true;
        for(int i = 0 ; i <= 2 ; ++i) {
            for(int j = 0 ; j <= 2 ; ++j) {
                if(dp[1].d[i][j] >= 4) return true;
            }
        }
        return false;
    }
    void print() {
        out(cnt);enter;
        for(int p = 0 ; p <= 1 ; ++p) {
            for(int j = 0 ; j <= 2 ; ++j) {
                for(int k = 0 ; k <= 2 ; ++k) {
                    out(dp[p].d[j][k]);space;
                }
                enter;
            }

        }
    }
}pool[100006];
map<MJ,int> zz;
int tot;
int dp[2][405][5005],cur,fac[405],invfac[405];
void dfs(MJ a) {
    if(zz.count(a)) return;
    if(a.win()) return;
    zz[a] = ++tot;pool[tot] = a;
    for(int i = 0 ; i <= 4 ; ++i) {
        dfs(Trans(a,i));
    }
}
int C(int n,int m) {
    if(n < m) return 0;
    return mul(fac[n],mul(invfac[m],invfac[n - m]));
}
void Solve() {
    read(N);
    int w,a;
    for(int i = 1 ; i <= 13 ; ++i) {
        read(w);read(a);
        cnt[w]++;
    }
    MJ t;
    dfs(t);
    dp[0][0][zz[t]] = 1;cur = 0;
    fac[0] = 1;
    for(int i = 1 ; i <= 400 ; ++i) fac[i] = mul(fac[i - 1],i);
    invfac[400] = fpow(fac[400],MOD - 2);
    for(int i = 399 ; i >= 0 ; --i) invfac[i] = mul(invfac[i + 1],i + 1);
    for(int i = 1 ; i <= N ; ++i) {
        memset(dp[cur ^ 1],0,sizeof(dp[cur ^ 1]));
        for(int j = 0 ; j <= 4 * (i - 1) ; ++j) {
            for(int h = 1 ; h <= tot ; ++h) {
                if(!dp[cur][j][h]) continue;
                for(int k = max(cnt[i],0) ; k <= 4 ; ++k) {
                    MJ nxt = Trans(pool[h],k);
                    if(nxt.win()) continue;
                    update(dp[cur ^ 1][j + k][zz[nxt]],mul(dp[cur][j][h],C(4 - cnt[i],k - cnt[i])));
                }
            }
        }
        cur ^= 1;
    }
    int ans = 0;
    for(int j = 13 ; j <= 4 * N ; ++j) {
        for(int h = 1 ; h <= tot ; ++h) {
            update(ans,mul(dp[cur][j][h],mul(fac[j - 13],fac[4 * N - j])));
        }
    }
    ans = mul(ans,invfac[4 * N - 13]);
    out(ans);enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}

Guess you like

Origin www.cnblogs.com/ivorysi/p/10959425.html