Educational Codeforces Round 103 (A~E)

A. K-divisible Sum

/**
 * Educational Codeforces Round 103 (Rated for Div. 2)
 * c++11
 */

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

void solve()
{
    int n, k;
    scanf("%d%d", &n, &k);
    int ans;
    if (k < n) ans = 1+(n%k!=0);
    else ans = k/n+(k%n!=0);
    printf("%d\n", ans);
}
int main()
{
    int t = 1;
    scanf("%d", &t);
    while (t--) {
        solve();
    }
    return 0;
}

B. Inflation

/**
 * Educational Codeforces Round 103 (Rated for Div. 2)
 * c++11
 */

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

void solve()
{
    int n, k;
    scanf("%d%d", &n, &k);
    vector<int> p(n);
    for (auto &t : p) scanf("%d", &t);
    LL sum = p[0];
    LL ans = 0;
    for (int i = 1; i < n; sum += p[i], ++i) {
        if (sum*k >= p[i]*100LL) continue;
        LL t = (p[i]*100LL+k-1)/k;
        ans = max(t-sum, ans);
    }
    printf("%lld\n", ans);
}
int main()
{
    int t = 1;
    scanf("%d", &t);
    while (t--) {
        solve();
    }
    return 0;
}

C. Longest Simple Cycle(dp)

\(dp_i\) 代表以第 \(i\) 条链为右边界的 \(LSC(Longest\ Simple\ Cycle)\)

如:对第一个样例 \(dp_2=6,dp_3=4,dp_4=7,ans=max(6,4,7)=7\)

\(dp\) 可递推求得。

时间复杂度 \(O(n)\)

/**
 * Educational Codeforces Round 103 (Rated for Div. 2)
 * c++11
 */

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

void solve()
{
    int n;
    scanf("%d", &n);
    vector<int> c(n+1), a(n+1), b(n+1);
    for (int i = 1; i <= n; ++i) scanf("%d", &c[i]);
    for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
    for (int i = 1; i <= n; ++i) scanf("%d", &b[i]);
    vector<LL> dp(n+1);
    LL ans = 0;
    for (int i = 2; i <= n; ++i) {
        int t = abs(a[i]-b[i])+1;
        if (t == 1) {
            dp[i] = c[i]+t;
        }
        else {
            dp[i] = max(0LL+c[i]+t, dp[i-1]+c[i]-t+2);
        }
        // cout << '#' << dp[i];
        ans = max(ans, dp[i]);
    }
    // cout << endl;
    printf("%lld\n", ans);
}
int main()
{
    int t = 1;
    scanf("%d", &t);
    while (t--) {
        solve();
    }
    return 0;
}

D. Journey(dp)

根据题意,

若城市右侧道路为 \(RLRLRL\cdots\) 则可一直向右走。

若城市左侧道路为 \(\cdots RLRLRL\) 则可一直向左走。

\(dpL_i\) 为从 \(i\) 个城市向左走能通过的道路数, \(dpR_i\) 为从第 \(i-1\) 个城市向右走能通过的道路数。

从第 \(i\) 个城市出发能访问的城市数量为 \(dpL_{i}+dpR_{i+1}+1\)

时间复杂度 \(O(n)\)

/**
 * Educational Codeforces Round 103 (Rated for Div. 2)
 * c++11
 */

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 3e5+5;
char s[N];
int dpL[N], dpR[N];
void solve()
{
    int n;
    scanf("%d%*c", &n);
    gets(s+1);
    dpL[0] = 0;
    dpL[1] = (s[1] == 'L');
    for (int i = 2; i <= n; ++i) {
        if (s[i] != 'L') dpL[i] = 0;
        else if (s[i-1] != 'R') dpL[i] = 1;
        else dpL[i] = dpL[i-2]+2;
    }
    dpR[n+1] = 0;
    dpR[n] = (s[n] == 'R');
    for (int i = n-1; i >= 1; --i) {
        if (s[i] != 'R') dpR[i] = 0;
        else if (s[i+1] != 'L') dpR[i] = 1;
        else dpR[i] = dpR[i+2]+2;
    }
    for (int i = 0; i <= n; ++i) {
        printf("%d ", dpL[i]+dpR[i+1]+1);
    }
    puts("");
}
int main()
{
    int t = 1;
    scanf("%d", &t);
    while (t--) {
        solve();
    }
    return 0;
}

E. Pattern Matching(拓扑排序)

以模式串序号为顶点建图,若模式串 \(i\) 必须出现在模式串 \(j\) 前面,则从顶点 \(i\) 到顶点 \(j\) 建立一条有向边。

一个字符串最多可匹配 \(2^k\) 种模式, \(1\le k\le 4\) ,故可枚举与一个字符串匹配的所有模式串的下标,该字符串应最先匹配的模式串下标与其它下标之间存在有向边。

最终形成一个有向图,若有环,则不存在满足条件的序列;否则为 \(DAG\) 图,拓扑排序结果即为最终答案。

由于 \(k\) 很小,若模式串用哈希存储,则时间复杂度为 \(O(n)\) 级别。

/**
 * Educational Codeforces Round 103 (Rated for Div. 2)
 * c++11
 * 模式串不超过 27^4 = 531441 种
 */

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 1e6;
int pattern[N];

int encode(string &s)
{
    int res = 0;
    for (auto &c : s) {
        res *= 27;
        if (c == '_') res += 0;
        else res += c^0x60;
    }
    return res;
}
void solve()
{
    int n, m, k;
    cin >> n >> m >> k;
    vector< vector<int> > adj(n+1);
    vector<int> in(n+1);
    for (int i = 0; i < n; ++i) {
        string p; cin >> p;
        pattern[encode(p)] = i+1;
    }
    for (int i = 0; i < m; ++i) {
        string s; int mt;
        cin >> s >> mt;
        bool match = 0;
        for (int b = 0; b < (1<<k); ++b) {
            string t = s;
            {
                int x = b, i = 0;
                while (x) {
                    if (x&1) t[i] = '_';
                    ++i;
                    x >>= 1;
                }
            }
            int index = pattern[encode(t)];
            match |= (index == mt);
            if (index == 0 || index == mt) continue;
            else adj[mt].push_back(index), ++in[index];
        }
        if (!match) {
            cout << "NO";
            return;
        }
    }

    queue<int> Q;
    vector<int> ans;
    for (int i = 1; i <= n; ++i) {
        if (in[i] == 0) Q.push(i);
    }
    while (!Q.empty()) {
        int t = Q.front(); Q.pop();
        ans.push_back(t);
        for (int i = 0; i < adj[t].size(); ++i) {
            int nxt = adj[t][i];
            if (--in[nxt] == 0) Q.push(nxt);
        }
    }
    if (ans.size() != n) cout << "NO";
    else {
        cout << "YES" << endl;
        for (auto &i : ans) cout << i << ' ';
    }
}
int main()
{
    ios::sync_with_stdio(0); cin.tie(0);
    int t = 1;
    // scanf("%d", &t);
    while (t--) {
        solve();
    }
    return 0;
}
posted @ 2021-01-31 15:45  Zewbie  阅读(150)  评论(0)    收藏  举报