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 << '\n';
    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] << '\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 << '\n';
        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 << '\n';
    return 0;
}
View Code

 

E

太难了不会

posted @ 2020-01-27 22:37  19992147  阅读(240)  评论(0编辑  收藏  举报