Codeforces Round 1004 (Div. 2)-交互题、数学题

比赛主页:Codeforces Round 1004 (Div. 2)

目录:

A. Adjacent Digit Sums

B. Two Large Bags

C. Devyatkino

D. Object Identification

A. Adjacent Digit Sums

A. Adjacent Digit Sums

题意:

给定两个整数 x, y,问是否存在一个整数 n,使得 S(n) = x, S(n+1) = y

其中 S(n) 表示整数 n 的数位和

思路:

  • 如果发生进位,那么数位和的变化值将会是:进位次数 * 9-1,只需要判断( x - y+1 )% 9 是否为 0 即可
  • 前提是 x-y+1 > 0
  • 或则没有发生进位,那么 y=x+1
//      https://codeforces.com/contest/2067/problem/A

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MOD = 1e9 + 7;

int T, n, m, k;
void solve()
{
    cin >> n >> m;
    if ((n + 1 == m) || (n - m + 1 > 0 && (n - m + 1) % 9 == 0))
        cout << "YES\n";
    else
        cout << "NO\n";
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    T = 1;
    cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

B. Two Large Bags

B. Two Large Bags

题意:

有两个背包 a, b,一开始背包 a 中有 n 个数,你可以进行以下操作无限次:

  • 将 a 中的一个数字 number 放到 b 中
  • 如果 a、b 中都存在数字 number,那么背包 a 中的 number+1(数值+1,不是数量+1),背包 b 中的 number 不变

问是否可以通过任意次操作使得 a = b,即每种数字的数量都相同

思路:

  • 我们需要让每种数的出现次数为偶数,而且只能 +1,所以可以从后往前遍历
  • 如果 cnt[i] 是奇数,那么就需要将 i-1 的数 +1 得到 i
  • 那么需要多少个呢?
  • cnt[i] 是奇数,那么还需要 1 个 i-1,所以需要 1 个 i-1 变到 i,而且每种数必须出现偶数次,那么至少需要 3 个 i-1,
  • 那就再看 i-1 有多少个,需不需要往更小的数借数,以此类推,每层都需要 ans + 2
  • 如果到了哪一层 cnt[x](x<i) 足够变这么多个 i 了,那就继续往下遍历,找是奇数的位置
  • 如果最后遍历到 1 位置了,ans 还没有被消掉,那么就是 NO 了
//      https://codeforces.com/contest/2067/problem/B

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MOD = 1e9 + 7;

int T, n, m, k;
int cnt[1003];
void solve()
{
    cin >> n;
    for (int i = 0; i <= n; i++)
        cnt[i] = 0;
    for (int i = 0, x; i < n; i++)
        cin >> x, cnt[x]++;
    int ans = 1;
    for (int i = n; i >= 1; i--)
    {
        if (cnt[i] & 1)
        {
            while (i >= 1)
            {
                if (cnt[i - 1] >= ans + 2)
                {
                    cnt[i - 1] -= ans + 2;
                    ans = 1;
                    break;
                }
                else
                    ans = ans + 2 - cnt[i - 1];
                i--;
            }
            if (i < 1)
            {
                cout << "NO\n";
                return;
            }
        }
    }
    cout << "YES\n";
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    T = 1;
    cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

C. Devyatkino

C. Devyatkino

题意:

给定一个整数 n,可进行以下操作:

  • 给 n 加上 10^x - 1(x >= 1)即(9、99、999、...、99999999...)

求最少操作次数使得 n 的数位中存在 7

思路:

  • 答案不够超过 9,因为 9 * 9 = 1,9 * 8 = 2,9 * 7 = 3,末位从 1~9 都覆盖了,最多加 9 次
  • 加 n 位的 99...9 相当于在 n+1 位加 1,在末位上 -1
  • 暴力遍历 +9、+99、+999....,0 次、1 次、2次....
  • 时间复杂度 O(1e3)
//      https://codeforces.com/contest/2067/problem/C

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MOD = 1e9 + 7;

int T, n, m, k;
void solve()
{
    cin >> n;
    int ans = 10;
    for (int i = 0; i <= 10; i++)
    {
        for (int j = 0; j <= 9; j++)
        {
            int temp = n + j * (pow(10, i) - 1);
            while (temp)
            {
                if (temp % 10 == 7)
                {
                    ans = min(ans, j);
                    break;
                }
                temp /= 10;
            }
        }
    }
    cout << ans << "\n";
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    T = 1;
    cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

D. Object Identification

D. Object Identification

题意:

交互题

给定两个长度为 n 的数组 X、Y,你知道数组 X 的每个值,但是你不知道数组 Y 的值;知道对于每个下标 i 满足:X[i] != Y[i];知道对于所有组合(X[i], Y[i])都不同。

裁判预先设定了答案 A 或者答案 B,在程序运行中不会改变,答案需要你通过询问的方式来猜

  • 答案 A:一个由 n 个节点,n 条边组成的有向图,第 i 条边为 Xi -> Yi
  • 答案 B:一个平面坐标,由 n 个点组成,第 i 个点为 (Xi, Yi)

你最多可以做两次询问,每次询问格式为 "? i j"

裁判会回答一个整数 number

  • 如果答案是 A,那么 number 代表节点 i 到节点 j 的最短路的边数
  • 如果答案是 B,那么 number 代表第 i 个点到第 j 个点的曼哈顿距离,即 |Xi - Xj| + |Yi - Yj|

如果你已经知道答案,那么请输出 "! A" 表示你猜的答案为 A,或者 "! B" 表示你猜的答案为 B

思路:

  • 如果 x 不是排列,那么就看没出现的数,假设 a 没有出现过,那么只需要判断 (a,*),如果读入 0,那么就是 A,否则为 B
    • 因为如果是 A,那么如果不存在 a -> * 的路径,那么肯定读入 0,如果读入非 0,那么就是 B 了
  • 如果 x 是排列,查询等于 1,n 的位置,如果 读入的数相等并且大于等于 n-1,那说明是 B,否则为 A
    • 因为 如果是 A,那么两个节点之间的距离不会 > n-1,而且是有向图,也不肯能相等
//      https://codeforces.com/contest/2067/problem/D

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MOD = 1e9 + 7;

int T, n, m, k;
void solve()
{
    cin >> n;
    vector<int> v(n + 1, 0), g(n + 1);
    for (int i = 1; i <= n; i++)
        cin >> g[i], v[g[i]] = 1;
    int a, b;
    for (int i = 1; i <= n; i++)
    {
        if (v[i] == 0)
        {
            cout << "? " << i << " " << 1 + (i == 1) << endl;
            cout.flush();
            cin >> a;
            cout << (a == 0 ? "! A" : "! B") << endl;
            cout.flush();
            return;
        }
    }
    int idx1, idxn;
    for (int i = 1; i <= n; i++)
    {
        if (g[i] == 1)
            idx1 = i;
        if (g[i] == n)
            idxn = i;
    }
    cout << "? " << idx1 << " " << idxn << endl;
    cout.flush();
    cin >> a;
    cout << "? " << idxn << " " << idx1 << endl;
    cout.flush();
    cin >> b;
    cout << ((a == b && a >= n - 1) ? "! B" : "! A") << endl;
    cout.flush();
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    T = 1;
    cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}
posted @ 2025-03-22 12:06  明天天晴KKK  阅读(14)  评论(0)    收藏  举报