Loading

Codeforces Round 1004 (Div. 2) 赛时记录

前言

赶紧打完补题
晚上睡觉还是盖被子吧, 太 tm 冷了
一会搜一下神秘教程, 然后就这样, 还剩下一堆题
记得问 关于最小生成树和最大流问题

注意效果剪枝, 然后就是听讲

\(\rm{A}\)

思路

样例给出的

  • \(y - x = 1\)
    显然可以构造
  • \(y = 1\)
    如果 \(x | 9\) , 显然可以构造

更一般的

  • \(y - x = 1\)
    显然可以构造
  • 进位
    本质上就是 \(9x \to 1\) , 差值如果可以构造成 \(9x - 1\) 的形式即可

代码

#include <bits/stdc++.h>

void solve() {
    int a, b; scanf("%d %d", &a, &b);
    if ((b - a) == 1 || (a - b) % 9 == 8) printf("Yes\n");
    else printf("No\n");
}

int main()
{
    int t; scanf("%d", &t);
    while (t--) solve();

    return 0;
}

\(\rm{B}\)

思路

题意

给定两个可重数集 a,ba, b
你可以

  • 移动 aa 中的某个数到 bb
  • 如果 xa,xbx \in a, x \in b , 让 xx+1x \gets x + 1

求最终是否可以让 a,ba, b 中内容相同

性质

一个数 xx 倘若出现了 >2> 2 次, 那么把剩下的部分全部丢给 x+1x + 1 , 一定可以处理出最后的结果
如果过程中一个数仅仅出现了 11 次, 或者最后那个数出现了奇数次, 那么就完蛋

代码

#include <bits/stdc++.h>
const int MAXN = 1020;
int a[MAXN];
int app[MAXN];

void solve() {
    int n; scanf("%d", &n);
    int mn = n + 1, mx = 0;
    memset(app, 0, sizeof app);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]), app[a[i]]++, mn = std::min(mn, a[i]), mx = std::max(mx, a[i]);

    for (int i = mn; i <= mx; i++) {
        if (app[i] == 1 || (i == mx && (app[i] % 2) == 1)) { printf("No\n"); return; }
        if (i == mx) { printf("Yes\n"); return; }
        if (app[i] > 2) app[i + 1] += app[i] - 2;
    }
}

int main()
{
    int t; scanf("%d", &t);
    while (t--) solve();

    return 0;
}

总结

一类操作问题

一般是找到一种统一的操作方式, 使得能被构造的一定可以构造
一种思想是解决当前的一部分, 余下的全部转化给下一个

\(\Delta \neq 1\) 的奇偶性问题的一种传递思想就是直接把余下的部分扔下去, 可以链式处理

\(\rm{C}\)

思路

题意

给定一个正整数 nn
在一次操作中, 你可以向 nn 添加任何只包含数字 99 的正整数, 该数字可以重复多次

为了使数字 nn 在其十进制表示中至少包含一个数字 77, 所需的最小操作次数是多少

答案上界

发现一直在个位加上 99 , 无论什么情况都可以在 88 次之内解决
所以答案上界确定

但好像没有什么用啊

一次操作只有 \(9\) 种情况, 直接乱搜即可

代码

#include <bits/stdc++.h>
#define int long long

int ans;
int pow10[12];
int p[12];
bool check(int now) {
    while (now) {
        if (now % 10 == 7) return true;
        now /= 10;
    }
    return false;
}
bool flag;
void dfs(int now, int tmp, int lst) {
    if (now > 10) return;
    for (int i = lst; i >= 0; i--) if ((p[now] + tmp + i * 9) % 10 == 7) { flag = true; return; }
    for (int i = lst; i >= 0; i--) {
        dfs(now + 1, (p[now] + tmp + i * 9) / 10, i);
    }
}

void solve() {
    ans = 8;
    int n; scanf("%lld", &n);
    int cnt = 0;
    memset(p, 0, sizeof p);
    if (check(n)) { printf("0\n"); return; }
    while (n) {
        p[++cnt] = n % 10;
        n /= 10;
    }
    for (int ans = 1; ans <= 8; ans++) {
        if ((p[1] + 0 + ans * 9) % 10 == 7) {
            printf("%lld\n", ans); return;
        }
        flag = false;
        dfs(2, (p[1] + 0 + ans * 9) / 10, ans);
        if (flag) { printf("%lld\n", ans); return; }
    }
}
signed main()
{
    pow10[0] = 1; for (int i = 1; i <= 10; i++) pow10[i] = pow10[i - 1] * 10;
    int t; scanf("%lld", &t);
    while (t--) solve();
    return 0;
}

总结

两种乱搞题

  • 数据范围小的
  • 答案范围小的
posted @ 2025-02-12 09:53  Yorg  阅读(102)  评论(0)    收藏  举报