2025春训第十七场

StarStar
3 min read

A. 最大公约数

直接枚举 1 ~ n 对于每一个数从他不等于自己的约数里面找个最大的,然后全部取个 max。

#include <iostream>
#include <cmath>

using namespace std;

int main() {
    int n, res = 1;
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        int l = sqrt(i);
        for (int j = 2; j <= l; ++j) {
            if (i % j == 0) {
                res = max(res, i / j);
                break;
            }
        }
    }
    cout << res << endl;
    return 0;
}

B. 数的变换

非常的水。

  • 约数中每有一个约数 2,次数 + 1;

  • 每有一个约数 3,次数 + 2(因为算完之后还需要处理造出来的一个 2;

  • 每有一个约数 5,次数 + 3(因为算完之后还需要处理造出来的两个 2);

#include <iostream>

using namespace std;

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        long long n, t = 0;
        scanf("%lld", &n);
        while (n % 5 == 0) n /= 5, t += 3;
        while (n % 3 == 0) n /= 3, t += 2;
        while (n % 2 == 0) n /= 2, t ++;
        if (n == 1)
            printf("%lld\n", t);
        else
            printf("-1\n");
    }
    return 0;
}

C. 回文

这道题其实可以直接暴力,因为一共只可能有 \(\binom{2}{26}\)种可能的不能配对的方式,于是就有不多于 \(\binom{2}{26}^2\)种可能的交换情况,于是直接枚举所有情况交换即可。

#include <iostream>
#include <algorithm>
#include <map>

using namespace std;

int a[26];
map<pair<int, int>, int> mp;
int mn = 0x3f3f3f3f;

int ord(char c) {
    return c - 'a';
}

long long getmin(int x, int y) {
    return min(min(a[x], a[y]), mn * 2);
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int n;
    cin >> n;
    for (int i = 0; i < 26; ++i) {
        cin >> a[i];
        mn = min(mn, a[i]);
    }
    string s;
    cin >> s;
    s = ' ' + s;
    long long res = 0;
    for (int i = 1; i <= (n / 2); ++i) {
        if (s[i] != s[n - i + 1]) {
            res += min(min(a[ord(s[i])], a[ord(s[n - i + 1])]), mn * 2);
            int lv = ord(s[i]), rv = ord(s[n - i + 1]);
            if (lv > rv) swap(lv, rv);
            mp[{lv, rv}]++;
        }
    }
    long long ss = 0;
    for (auto [p, t] : mp) {
        if (t > 1) {
            ss = min(ss, -2ll * min(min(a[p.first], a[p.second]), mn * 2));
        }
        for (auto [pp, _] : mp) {
            if (pp == p) continue;
            ss = min(ss,
                min(
                    getmin(p.first, pp.first) + getmin(p.first, pp.second),
                    getmin(p.first, pp.second) + getmin(p.second, pp.first)
                ) - getmin(p.first, p.second) - getmin(pp.first, pp.second)
            );
        }
    }
    res = min(res, res + ss);
    cout << res << endl;
    return 0;
}

E. 船长的自助餐

一道数据比较友好的 dp 题,至于我为什么在红温,当然是没好好读题就去做了 😇😇😇

连着吃 \(\lceil \log_{\frac{2}{3}}{M} \rceil\)次胃容量就变成 0 了,当然如果你没发现这个,直接把胃容量整个当一个状态塞进去应该也是不会 TLE 的,如果能离散化一下会更快。

记 \(f_{i, j, 1}\) 为吃到第 i 天,已经连续吃了 j 次,并且第 i 天吃了的情况下能吃的最大值; \(f_{i, j, 0}\) 为第 i 天没吃的情况下的最大值。

\[f_{i, 1, 0} = \max \{ f_{i - 1, j, 0} \}\]

\[f_{i, j, 0} = \max \{f_{i - 1, j, 0}, f_{i - 1, j, 1} \} \ (j \neq 1)\]

\[f_{i, j, 1} = \max\{f_{i - 1, j, 0} + \min \{m_j, A_i\}, f_{i - 1, j - 1, 1} + \min \{m_j, a_i \} \} \ (m_j = 连续吃了 j 次后胃容量)\]

#include <iostream>
#define int long long

using namespace std;

const int N = 1010;

int n, m[70], a[N];
long long f[N][70][2];

signed main() {
    scanf("%lld%lld", &n, &m[1]);
    int l;
    for (l = 2; m[l - 1]; ++l) m[l] = m[l - 1] * 2 / 3;
    l--;
    for (int i = 1; i <= n; ++i) {
        scanf("%lld", &a[i]);
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= l; ++j) {
            f[i][1][0] = max(f[i][1][0], f[i - 1][j][0]);
        }
        for (int j = 1; j <= l; ++j) {
            f[i][j][0] = max(f[i][j][0], max(f[i - 1][j][0], f[i - 1][j][1]));
        }
        f[i][1][1] = f[i - 1][1][0] + min(m[1], a[i]);
        for (int j = 2; j <= l; ++j) {
            f[i][j][1] = max(f[i - 1][j][0] + min(m[j], a[i]), f[i - 1][j - 1][1] + min(m[j], a[i]));
        }
    }
    long long res = 0;
    for (int i = 1; i <= l; ++i) {
        res = max(res, max(f[n][i][0], f[n][i][1]));
    }
    printf("%lld\n", res);
    return 0;
}
0
Subscribe to my newsletter

Read articles from Star directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Star
Star

A Chinese OIer and a tosser.