zoukankan      html  css  js  c++  java
  • UOJ346

    [题目链接]

    https://uoj.ac/problem/346

    [题解]

    首先定义每个位置的值 (val_{i} = min{w}) , 也就是覆盖这个位置的 (w) 值最小值。 这样 , 最终这个位置填的权值是不能超过 (val) 的。

    注意到每种权值互相独立 , 不妨分别计算将方案数相乘。

    对于每种权值 , 考虑动态规划。

    (dp_{i , j}) 表示前 (i) 个区间 , 上次放置在第 (j) 个区间的方案数。 这样只需考虑当前这个区间选 / 不选点转移即可。

    时间复杂度 : (O(Q ^ 3))

    [代码]

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long LL;
    
    #define rep(i , l , r) for (int i = (l); i < (r); ++i)
    
    const int MN = 2005, mod = 998244353;
    
    set < int > st;
    int n, q, A, l[MN], r[MN], w[MN], s[MN], t[MN], dp[MN][MN], mn[MN], mx[MN], len;
    
    inline void inc(int &x, int y) {
        x = x + y < mod ? x + y : x + y - mod;
    }
    inline void chkmin(int &x, int y) {
        x = min(x, y);
    }
    inline void chkmax(int &x, int y) {
        x = max(x, y);
    }
    inline int qPow(int a, int b) {
        int c = 1;
    
        for (; b; b >>= 1, a = 1ll * a * a % mod)
            if (b & 1)
                c = 1ll * c * a % mod;
    
        return c;
    }
    inline int calc(int now) {
        int tot = 0;
    
        for (int i = 1; i <= len; ++i)
            if (mn[i] == now)
                t[++tot] = i;
    
        if (!tot)
            return -1;
    
        for (int i = 1; i <= tot; ++i)
            mx[i] = 0;
    
        for (int i = 1; i <= q; ++i)
            if (w[i] == now) {
                int L = lower_bound(t + 1, t + 1 + tot, l[i]) - t,
                    R = lower_bound(t + 1, t + 1 + tot, r[i]) - t - 1;
                chkmax(mx[R], L);
            }
    
        dp[0][0] = 1;
    
        for (int i = 1; i <= tot; ++i) {
            dp[i][i] = 0;
            int choose0 = qPow(now - 1, s[t[i] + 1] - s[t[i]]);
            int choose1 = qPow(now, s[t[i] + 1] - s[t[i]]);
    
            for (int j = 0; j < i; ++j) {
                if (j >= mx[i])
                    dp[i][j] = 1ll * dp[i - 1][j] * choose0 % mod;
                else
                    dp[i][j] = 0;
    
                inc(dp[i][i], 1ll * dp[i - 1][j] * ((choose1 + mod - choose0) % mod) % mod);
            }
        }
    
        int res = 0;
    
        for (int i = 0; i <= tot; ++i)
            inc(res, dp[tot][i]);
    
        return res;
    }
    inline void solve() {
        st.clear();
        scanf("%d%d%d", &n, &q, &A);
        s[len = 1] = 1;
    
        for (int i = 1; i <= q; ++i) {
            scanf("%d%d%d", &l[i], &r[i], &w[i]), ++r[i];
            s[++len] = l[i], s[++len] = r[i], st.insert(w[i]);
        }
    
        s[++len] = n + 1, sort(s + 1, s + 1 + len);
        len = unique(s + 1, s + 1 + len) - s - 1;
    
        for (int i = 1; i <= len; ++i)
            mn[i] = 1 + A;
    
        for (int i = 1; i <= q; ++i) {
            l[i] = lower_bound(s + 1, s + 1 + len, l[i]) - s;
            r[i] = lower_bound(s + 1, s + 1 + len, r[i]) - s;
    
            for (int j = l[i]; j < r[i]; ++j)
                chkmin(mn[j], w[i]);
        }
    
        int res = 1, x;
    
        for (set < int > :: iterator it = st.begin(); it != st.end(); ++it) {
            if (~(x = calc(*it)))
                res = 1ll * res * x % mod;
            else {
                puts("0");
                return;
            }
        }
    
        for (int i = 1; i < len; ++i)
            if (mn[i] == A + 1)
                res = 1ll * res * qPow(A, s[i + 1] - s[i]) % mod;
    
        printf("%d
    ", res);
    }
    int main() {
    
        int T;
        scanf("%d", &T);
    
        while (T--)
            solve();
    
        return 0;
    }
  • 相关阅读:
    Mvc+三层(批量添加、删除、修改)
    js中判断复选款是否选中
    EF的优缺点
    Git tricks: Unstaging files
    Using Git Submodules
    English Learning
    wix xslt for adding node
    The breakpoint will not currently be hit. No symbols have been loaded for this document."
    Use XSLT in wix
    mfc110ud.dll not found
  • 原文地址:https://www.cnblogs.com/evenbao/p/14029624.html
Copyright © 2011-2022 走看看