zoukankan      html  css  js  c++  java
  • Dwango Programming Contest 6th 题解

    A

    枚举一下

    #include <bits/stdc++.h>
    using namespace std;
    int n;
    string End;
    string s[55];
    int t[55];
    int main() {
        cin >> n;
        for(int i = 1; i <= n; ++i) {
            cin >> s[i] >> t[i];
        }
        cin >> End;
        int ans = 0;
        for(int i = n; i; --i) {
            if(s[i] == End) {
                break;
            }
            ans += t[i];
        }
        cout << ans;
        return 0;
    }
    View Code

    B

    期望

    按每个空隙计算 对于第$i$个空隙 对于第$j$个跨过这段的概率是$frac{1}{i-j+1}$ 因为跨过当且仅当$[j+1,i]$之间都不先于$j$合并 求一个逆元前缀和即可

    还可以这样做 $dp[i]$表示第$i$个空隙期望经过人数

    那么$dp[1] = 1$

    $dp[n] = dp[n - 1] + frac{1}{n}$

    因为考虑任意一个人动 只有最右边的人动会造成贡献  

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5 + 5, P = 1e9 + 7;
    int n;
    int x[maxn], inv[maxn];
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        cin >> n;
        for(int i = 1; i <= n; ++i) {
            cin >> x[i];
        }
        inv[1] = 1;
        for(int i = 2; i <= n; ++i) {
            inv[i] = 1LL * (P - P / i) * inv[P % i] % P;
        }
        for(int i = 2; i <= n; ++i) {
            inv[i] = (inv[i] + inv[i - 1]) % P;
        }
        int ans = 0;
        for(int i = 1; i < n; ++i) {
            ans = (ans + 1LL * inv[i] % P * (x[i + 1] - x[i]) % P) % P;
        }
        for(int i = 1; i < n; ++i) {
            ans = 1LL * ans * i % P;
        }
        cout << ans << '
    ';
        return 0;
    }
    View Code

    C

    乘上组合数后相当于计算所有情况下的开心值

    问题可以转化成有一个$K*N$的表格 每一行涂$a[i]$个红格子 再将每一列的红格子中选一个涂蓝的方案数

    $dp[i][j]$表示前i行涂了j列

    转移$dp[i][j] * C(n - j, l) * C(n - l, a[i + 1] - l)  -> dp[i + 1][j + l]$

    表示下一行先钦定l个蓝色格子 且这些蓝色格子所在列没有蓝色格子 剩下随便选涂红色

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1005, P = 1e9 + 7;
    int n, k;
    int a[maxn];
    int c[maxn][maxn], dp[22][maxn];
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        cin >> n >> k;
        for(int i = 1; i <= k; ++i) {
            cin >> a[i];
        }
        c[0][0] = 1;
        for(int i = 1; i <= n; ++i) {
            c[i][0] = 1;
            for(int j = 1; j <= i; ++j) {
                c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % P;
            }
        }
        dp[0][0] = 1;
        for(int i = 0; i < k; ++i) {
            for(int j = 0; j <= n; ++j) {
                for(int l = 0; l + j <= n && l <= a[i + 1]; ++l) {
                    dp[i + 1][j + l] = (dp[i + 1][j + l] + 1LL * dp[i][j] * c[n - j][l] % P * c[n - l][a[i + 1] - l] % P) % P;
                }
            }
        }
        cout << dp[k][n] << '
    ';
        return 0;
    }
    View Code

    D

    问题转化成求补图字典序最小的哈密尔顿回路

    题解里写这样貌似的路径很好找 于是先贪心填 如果当前存在入度等于剩下除自身外点数的点 那么填上 否则不合法 否则就填字典序最小的 用两个set维护一下

    但是会不合法 于是最后几个点爆搜一下 具体证明不会

    这道题告诉我们碰见这种npc问题要考虑乱搞贪心以及爆搜 说不定就过了

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5 + 5;
    int n;
    int a[maxn], d[maxn], used[maxn], ans[maxn];
    set<int> s;
    set<pair<int, int> > e;
    vector<int> b;
    void dfs(int p, int ban) {
        if(p == n + 1) {
            for(int i = 1; i <= n; ++i) {
                cout << ans[i] << ' ';
            }
            cout << '
    ';
            exit(0);
        }
        for(int i = 0; i < b.size(); ++i) {
            if(!used[b[i]] && b[i] != ban) {
                used[b[i]] = 1;
                ans[p] = b[i];
                dfs(p + 1, a[b[i]]);
                used[b[i]] = 0;
            }
        }
    }
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        cin >> n;
        for(int i = 1; i <= n; ++i) {
            cin >> a[i];
            ++d[a[i]];
        }
        for(int i = 1; i <= n; ++i) {
            s.emplace(i);
        }
        for(int i = 1; i <= n; ++i) {
            e.emplace(-d[i], i);
        }
        int ban = 0;
        for(int i = 1; i <= n - 5; ++i) {
            int u;
            if(-e.begin() -> first == n - i) {
                u = e.begin() -> second;
            } else if(*s.begin() != ban) {
                u = *s.begin();
            } else {
                u = *next(s.begin());
            }
            s.erase(u);
            e.erase({-d[u], u});
            used[u] = 1;
            if(!used[a[u]]) {
                e.erase({-d[a[u]], a[u]});
                --d[a[u]];
                e.emplace(-d[a[u]], a[u]);
            }
            ban = a[u];
            ans[i] = u;
        }
        b.assign(s.begin(), s.end());
        dfs(max(1, n - 4), ban);
        cout << -1 << '
    ';
        return 0;
    }
    View Code

    E

    太难了不会

  • 相关阅读:
    [leetcode]43. Multiply Strings
    [leetcode]387. First Unique Character in a String
    Penetration Test
    Penetration Test
    Penetration Test
    Penetration Test
    Penetration Test
    Penetration Test
    Penetration Test
    Penetration Test
  • 原文地址:https://www.cnblogs.com/19992147orz/p/12237096.html
Copyright © 2011-2022 走看看