2024牛客寒假算法基础集训营3

A

void solve()
{
    string s1, s2;
    cin >> s1 >> s2;
    int a = 0, b = 0;
    if (s1[0] <= 'z' && s1[0] >= 'a')
        a = s1[0] - 'a';
    else
        a = s1[0] - 'A';
    if (s2[0] <= 'z' && s2[0] >= 'a')
        b = s2[0] - 'a';
    else
        b = s2[0] - 'A';
    cout << (a == b ? "Yes" : "No") << endl;
}

B

一定可以全消掉,所以答案只跟长度有关

void solve()
{
    int n;
    cin >> n;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    cout << (n % 2 ? "qcjj" : "zn" )<< endl;
}

C

1.hash:

struct Hash
{
    const int base1 = 1361, base2 = 1301;
    const int p1 = 1000000123, p2 = 1000000021;
    int n;
    vector<int> a1, a2, c1, c2;
    Hash(int _n) : n(_n), a1(n + 10), a2(n + 10), c1(n + 10, 0), c2(n + 10) {}
    void build(int n, vector<char> arr)
    {
        ll res = 0;
        c1[0] = 1, c2[0] = 1;
        for (int i = 1; i <= n; i++)
        {
            res = (res * base1 + arr[i]) % p1;
            c1[i] = 1ll * c1[i - 1] * base1 % p1;
            a1[i] = res;
        }
        res = 0;
        for (int i = 1; i <= n; i++)
        {
            res = (res * base2 + arr[i]) % p2;
            c2[i] = 1ll * c2[i - 1] * base2 % p2;
            a2[i] = res;
        }
    }
    pii query(int l, int r) // 询问子串的哈希值
    {
        int hashval1 = (a1[r] - 1ll * a1[l - 1] * c1[r - l + 1] % p1 + p1) % p1;
        int hashval2 = (a2[r] - 1ll * a2[l - 1] * c2[r - l + 1] % p2 + p2) % p2;
        return {hashval1, hashval2};
    }
};
void solve()
{
    int n, m;
    cin >> n >> m;
    vector<char> s(n + 1), t(m + 1);
    for (int i = 1; i <= n; i++)
        cin >> s[i];
    for (int i = 1; i <= m; i++)
        cin >> t[i];
    Hash hs(n), hrs(n), ht(m), hrt(m);
    hs.build(n, s), ht.build(m, t);
    reverse(s.begin() + 1, s.end());
    reverse(t.begin() + 1, t.end());
    hrs.build(n, s), hrt.build(m, t);
    vector<int> ans1, ans2;
    for (int i = 1; i <= min(n, m); i++)
        if (hs.query(1, i) == hrs.query(n - i + 1, n) && ht.query(m - i + 1, m) == hrt.query(1, i))
            if (hs.query(1, i) == ht.query(m - i + 1, m))
                ans1.push_back(i);
    for (int i = 1; i <= min(n, m); i++)
    {
        if (ht.query(1, i) == hrt.query(m - i + 1, m) && hs.query(n - i + 1, n) == hrs.query(1, i))
            if (ht.query(1, i) == hs.query(n - i + 1, n))
                ans2.push_back(i);
    }
    if (ans1.empty() || ans2.empty())
        cout << "-1" << endl;
    else
    {
        int res = 0;
        for (auto i : ans1)
        {
            int l = 0, r = ans2.size() - 1;
            while (l < r)
            {
                int mid = (l + r + 1) >> 1;
                if (ans2[mid] + i <= n && ans2[mid] + i <= m)
                    l = mid;
                else
                    r = mid - 1;
            }
            if (ans2[l] + i <= n && ans2[l] + i <= m)
                res = max(res, (i + ans2[l]) * 2);
        }
        cout << res << endl;
    }
}

2.kmp

3.manacher

4.exkmp

5.sa

D

预处理左右端点的最大字段和,枚举交换位置即可

void solve()
{
    int n, k;
    cin >> n >> k;
    vector<ll> a(n + 1), dpl(n + 10, 0), dpr(n + 10, 0);
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    ll res = -1e18;
    for (int i = 1; i <= n; i++)
    {
        dpl[i] = (dpl[i - 1] > 0 ? dpl[i - 1] + a[i] : a[i]);
        res = max(res, dpl[i]);
    }
    for (int i = n; i >= 1; i--)
    {
        dpr[i] = (dpr[i + 1] > 0 ? dpr[i + 1] + a[i] : a[i]);
        res = max(res, dpr[i]);
    }
    if (k)
    {
        for (int i = 1; i < n; i++)//i i+1
        {
            res = max(res, dpl[i - 1] + a[i + 1]);
            res = max(res, dpr[i + 2] + a[i]);
        }
    }
    cout << res << endl;
}

G/H

暴力枚举所有情况

void solve()
{
    int n;
    cin >> n;
    vector<array<int, 3>> a(n);
    vector<int> val(10, 0);
    for (auto &[u, v, w] : a)
        cin >> u >> v >> w;
    bool ans = 0;
    auto chk = [&]() -> bool
    {
        for (auto [u, v, w] : a)
        {
            int res = val[u] < val[v];
            if (res != w)
                return false;
        }
        return true;
    };
    for (int i = 1; i <= 3; i++)
        for (int j = 1; j <= 3; j++)
            for (int k = 1; k <= 3; k++)
            {
                val[1] = i, val[2] = j, val[3] = k;
                ans |= chk();
            }
    cout << (ans ? "Yes" : "No") << endl;
}

J

处理出每个人被选中的概率,期望等于$\sum {p_i *1} $

void solve()
{
    auto qmi = [&](ll a, ll b)
    {
        ll res = 1;
        while (b)
        {
            if (b & 1)
                res = res * a % mod;
            b >>= 1;
            a = a * a % mod;
        }
        return res;
    };
    int n, m, k;
    cin >> n >> m >> k;
    vector<vector<int>> e(n + m + 1);
    vector<ll> d(n + m + 1, 1);
    for (int i = 1; i <= k; i++)
    {
        int u, v;
        cin >> u >> v;
        v += n;
        e[u].push_back(v), e[v].push_back(u);
    }
    for (int i = 1; i <= n + m; i++)
    {
        int sum = e[i].size();
        if (sum)
        {
            ll p = qmi(sum, mod - 2);
            p = (1 - p + mod) % mod;
            for (auto to : e[i])
                d[to] = (d[to] * p % mod) % mod;
        }
    }
    for (int i = 1; i <= n + m; i++)
        d[i] = (1 - d[i] + mod) % mod;
    ll ans1 = 0, ans2 = 0;
    for (int i = 1; i <= n; i++)
        ans1 = (ans1 + d[i]) % mod;
    for (int i = n + 1; i <= n + m; i++)
        ans2 = (ans2 + d[i]) % mod;
    cout << "modint" << endl;
    cout << ans1 << " " << ans2 << endl;
}

K

每次暴力拓展红/黑节点即可

void solve()
{
    int n, m, cnt = 1, sum;
    cin >> n >> m;
    sum = n + m;
    vector<pii> ans(n + m + 1, {-1, -1});
    if (!n)
    {
        cout << "No" << endl;
        return;
    }
    n--;
    vector<int> b, w;
    b.push_back(1);
    while (n > 0 || m > 0)
    {
        bool f = 0;
        if (n > 0 && w.size())
        {
            f = 1;
            n -= 2;
            auto t = w.back();
            w.pop_back();
            ans[t] = {cnt + 1, cnt + 2};
            cnt += 2;
            b.push_back(ans[t].x), b.push_back(ans[t].y);
        }
        if (m > 0 && b.size())
        {
            f = 1;
            m -= 2;
            auto t = b.back();
            b.pop_back();
            ans[t] = {cnt + 1, cnt + 2};
            cnt += 2;
            w.push_back(ans[t].x), w.push_back(ans[t].y);
        }
        if (!f)
            break;
    }
    if (n == 0 && m == 0)
    {
        cout << "Yes" << endl;
        for (int i = 1; i <= sum; i++)
            cout << ans[i].x << " " << ans[i].y << endl;
    }
    else
        cout << "No" << endl;
}

L/M

dp

因为\((i,j),(j,i)\)是两种情况,所以要反转过来再来一遍

ll f[N][N];              // 接长度为i的后缀,mod36=j
void solve()
{
    int n;
    cin >> n;
    map<ll, ll> mp;
    vector<ll> a(n + 1);
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    auto cal = [&](ll x) -> int
    {
        int res = 0;
        while (x > 0)
            x /= 10, res++;
        return res;
    };
    ll ans = 0;
    for (int i = 1; i <= n; i++)
    {
        int len = cal(a[i]);
        ans += f[len][(36 - a[i] % 36) % 36];
        ll now = a[i] % 36;
        for (int j = 1; j <= 18; j++)
        {
            now = now * 10 % 36;
            f[j][now]++;
        }
    }
    memset(f, 0, sizeof f);
    reverse(a.begin() + 1, a.end());
    for (int i = 1; i <= n; i++)
    {
        int len = cal(a[i]);
        ans += f[len][(36 - a[i] % 36) % 36];
        ll now = a[i] % 36;
        for (int j = 1; j <= 18; j++)
        {
            now = now * 10 % 36;
            f[j][now]++;
        }
    }
    cout << ans << endl;
}
posted @ 2024-02-29 18:32  0x3ea  阅读(4)  评论(0编辑  收藏  举报