A

#include <iostream>
using namespace std;

int main()
{
    
    int z1, z2, k1, k2;
    cin >> z1 >> z2 >> k1 >> k2;
    int cnt = 0;
    cnt += (z1 == 1 && k1 == 3) || (z1 == 2 && k1 == 1) || (z1 == 3 && k1 == 2);
    cnt += (z1 == 1 && k2 == 3) || (z1 == 2 && k2 == 1) || (z1 == 3 && k2 == 2);
    cnt += (z2 == 1 && k1 == 3) || (z2 == 2 && k1 == 1) || (z2 == 3 && k1 == 2);
    cnt += (z2 == 1 && k2 == 3) || (z2 == 2 && k2 == 1) || (z2 == 3 && k2 == 2);
    cout << cnt * 25 << "%\n";
    return 0;
}

B

#include <iostream>
using namespace std;
typedef long long ll;

int main() {

    ll n, k;
    cin >> n >> k;
    if (n == 1) { // 只有1台机器,无需时间
        cout << 0 << '\n';
        return 0;
    }
    ll cnt = 1;  // 已更新的机器数量
    ll ans = 0;  // 总耗时
    
    // 阶段1:快速翻倍(数量<k,电缆够用)
    while (cnt < k && cnt * 2 < n) {
        cnt *= 2;
        ans++;
    }
    
    // 阶段2:剩余机器匀速传输(每小时最多加k台)
    ll rem = n - cnt;
    // 向上取整:(rem + k -1) / k
    ans += (rem + k - 1) / k;
    
    cout << ans << '\n';
    
    return 0;
}

C

#include <iostream>
#include <cmath>
using namespace std;

int main()
{
    long long l, r;
    cin >> l >> r;
    // 右边界:最大的奇数k,满足k² ≤ r
    long long R = sqrt(r);
    R = (R % 2 == 0) ? R - 1 : R;
    // 左边界:最小的奇数k,满足k² ≥ l
    long long L = sqrt(l - 1) + 1;
    L = (L % 2 == 0) ? L + 1 : L;

    // 计算个数,无结果则为0
    cout << (L > R ? 0 : (R - L) / 2 + 1);
    return 0;
}

D

小Z必胜,即他必须有一个手势,能赢过对方的两个手势。

使用数组存储胜负关系,并计数小Z的必胜手势种类数,记为 cc,则这个必胜花样搭配其他任何一种手势都可以赢,左右手还可以互换,即总数为 2nc2nc

注意这 cc 种必胜手势两两选择被重复计数,因此要减去 ccc*c

#include <bits/stdc++.h>
using namespace std;
const int N = 5e3 + 5;
int n, m, b[N][N], f, s;
char a[N][N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= i; j++)
        {
            cin >> a[i][j];
            if (a[i][j] == 'S')
                b[i][j] = 1;
            if (a[i][j] == 'F')
                b[j][i] = 1;
        }
    while (m--)
    {
        cin >> f >> s;
        int c = 0;
        for (int i = 1; i <= n; i++)
            c += (b[i][f] > 0 && b[i][s] > 0);
        cout << c * (2 * n - c) << '\n';
    }
}

E

因为初始 aia_i 都是正数,所以可以发现,最后的答案一定是一段连续区间和。合并次数为 mm,对应的是一段 m+1m+1 的区间。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    vector<ll> a(n + 1);
    vector<ll> pre(n + 1, 0);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        pre[i] = pre[i - 1] + a[i];
    }

    int window = m + 1;
    ll max_sum = 0;
    for (int i = window; i <= n; i++)
    {
        ll cur = pre[i] - pre[i - window];
        max_sum = max(max_sum, cur);
    }
    cout << max_sum << '\n';
    return 0;
}

F

三个纯 1 数相加不会产生任何进位,最终的和一定是「高位连续的 1 + 中间连续的 2 + 低位连续的 3」的固定结构。

先计算最后结果的长度 lenlen,可使用如下三重循环验证:

for (int i = 0; i <= len; i++)
  for (int j = 0; i + j <= len; j++)
    for (int k = 0; i + j + k <= len; k++)
        cnt++;

可以发现在 len=150len=150 时,cnt=585276>5e5cnt=585276>5e5

然后继续枚举 1,2,31,2,3 各自的长度,存入结构体进行排序:

  • 先按照总长度排序
  • 长度相同时,按照 11 的数量排序
  • 以上相同时,按照 22 的数量排序

最后定位出所要求的第 nn 大的结果

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

struct Node
{
    int i, j, k; // 分别对应1、2、3的个数
};

bool cmp(const Node &a, const Node &b)
{
    int len_a = a.i + a.j + a.k;
    int len_b = b.i + b.j + b.k;
    // 1. 先按总长度从小到大
    if (len_a != len_b)
        return len_a < len_b;
    // 2. 长度相同,1的个数越多越小
    if (a.i != b.i)
        return a.i > b.i;
    // 3. 1的个数相同,2的个数越多越小
    return a.j > b.j;
}

int main()
{
    ios::sync_with_stdio(false);
    cout.tie(nullptr);

    int n;
    cin >> n;

    vector<Node> v;

    // 枚举总长度,最多枚举到200足够覆盖n=5e5
    for (int len = 1; len <= 200; len++)
    {
        // 枚举1的个数i
        for (int i = 0; i <= len; i++)
        {
            // 枚举2的个数j
            for (int j = 0; j <= len - i; j++)
            {
                int k = len - i - j;
                // 3的个数至少为1
                if (k >= 1)
                    v.push_back({i, j, k});
            }
        }
        // 已经收集够n个以上就可以提前停,不用枚举更长的了
        if (v.size() >= n)
            break;
    }

    // 按数字从小到大排序
    sort(v.begin(), v.end(), cmp);

    // 取第n个(下标n-1)
    Node ans = v[n - 1];

    // 拼接输出
    string res;
    res.append(ans.i, '1');
    res.append(ans.j, '2');
    res.append(ans.k, '3');
    cout << res << '\n';

    return 0;
}

0 条评论

目前还没有评论...