Codeforces Round 931 (Div. 2)

Codeforces Round 931 (Div. 2)

A - Too Min Too Max

解题思路:

最大、最小、次大、次小。

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
typedef double db;
#define fi first
#define se second
using i128 = __int128_t;
using piii = pair<ll, pair<ll, ll>>;

void solve()
{
    int n;
    cin >> n;
    vector<ll> a(n + 1), b(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    ll ans = 0;
    sort(a.begin() + 1, a.end());
    ans = abs(a[n] - a[1]) + abs(a[1] - a[n - 1]) + abs(a[n - 1] - a[2]) + abs(a[2] - a[n]);
    cout << ans << endl;
}

int main()
{
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

B - Yet Another Coin Problem

解题思路:

\(30\)以内的数字用背包求最优凑法,\(30\)往上的\(15\)填到只剩下\(30\)以内。

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
typedef double db;
#define fi first
#define se second
using i128 = __int128_t;
using piii = pair<ll, pair<ll, ll>>;
ll f[100];
void solve()
{
    ll n;
    cin >> n;
    ll cnt = 0;
    if (n / 15 >= 2)
    {
        cnt += n / 15 - 1;
        n -= (n / 15 - 1) * 15;
    }
    cout << cnt + f[n] << endl;
}

int main()
{
    for (int i = 1; i <= 99; i++)
    {
        f[i] = 1e9;
    }
    f[0] = 0;
    for (int i = 1; i <= 99; i++)
    {
        int cur = 15;
        for (int j = 5; j >= 1; j--)
        {
            if (i >= cur)
            {
                f[i] = min(f[i - cur] + 1, f[i]);
            }
            cur -= j;
        }
    }
    // for (int i = 1; i <= 99; i++)
    // {
    //     cout << i << ' ' << f[i] << endl;
    // }
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

C - Find a Mine

解题思路:

第一次询问\((1, 1)\):存在一个答案在\(x + y = d+ 2\)这个对角线上。

求该对角线右上角\((x_1, y_1)\),左下角\((x_2,y_2)\)

询问\((x_1,y_1)\)

  • 如果返回是奇数,说明存在不在该对角线上的地雷距离\((x_1,y_1)\)更近。选择询问\((x_2,y_2)\),答案为\((x_2 + \frac{d}{2},y_2 + \frac{d}{2})\)
  • 如果返回是偶数,询问\((x_1 + \frac{d}{2},y_1 + \frac{d}{2})\),如果返回距离为\(0\)说明找到一个解;否则说明存在不在该对角线上的地雷距离\((x_1,y_1)\)更近,同上,转为询问\((x_2,y_2)\)

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
typedef double db;
#define fi first
#define se second
using i128 = __int128_t;
using piii = pair<ll, pair<ll, ll>>;

void ask(int x, int y)
{
    cout << "?" << ' ' << x << ' ' << y << endl;
    cout.flush();
}

void solve()
{
    int n, m;
    cin >> n >> m;
    ask(1, 1);
    ll d;
    cin >> d;
    if (d == 0)
    {
        cout << "!" << ' ' << 1 << ' ' << 1 << endl;
        return;
    }
    int x = 1;
    int y = 1;
    if (m - y >= d)
    {
        y += d;
    }
    else
    {
        int t = d;
        t -= m - y;
        y = m;
        x += t;
    }
    int a = 1;
    int b = 1;
    if (n - a >= d)
    {
        a += d;
    }
    else
    {
        int t = d;
        t -= n - a;
        a = n;
        b += t;
    }
    ask(x, y);
    cin >> d;
    if (d == 0)
    {
        cout << "!" << ' ' << x << ' ' << y << endl;
        return;
    }
    if (d & 1)
    {
        ask(a, b);
        cin >> d;
        if (d == 0)
        {
            cout << "!" << ' ' << a << ' ' << b << endl;
            return;
        }
        a -= d / 2;
        b += d / 2;
        cout << "!" << ' ' << a << ' ' << b << endl;
    }
    else
    {
        x += d / 2;
        y -= d / 2;
        ask(x, y);
        cin >> d;
        if (d == 0)
        {
            cout << "!" << ' ' << x << ' ' << y << endl;
        }
        else
        {
            ask(a, b);
            cin >> d;
            a -= d / 2;
            b += d / 2;
            cout << "!" << ' ' << a << ' ' << b << endl;
        }
    }
}

int main()
{

    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

D1 - XOR Break --- Solo Version

解题思路:

\((n \oplus m) < n\),那么一步直接变。

否则,对\(n\)进行变换,使得\((n \oplus m) < n\)。如果存在,改变换只需要一步。

如果\((n)_2 = 11011,(m)_2 = 00100\)这种形式,我们可以将\(n \to 10111\),即将距离\(n\)次高位\(1\)变为\(0\),然后低位全部变成\(1\)。此时,\(n \to x\),所有\(x \oplus m < x\)\(m\)都可直接变换,即运用题目法则\(x \to y\)

如果\(m\)的最高位\(1\)仅低于\(n\)的最高位\(1\),而不小于等于\(n\)的次高位\(1\)。我们发现,总是无法满足变换条件。

若我们先异或了\(m\)最高位的\(1\)\(x \oplus y > x\)

若我们先异或了\(n\)最高位的\(1\)\(x \oplus y < m\),后续一定也无法变为\(m\)

如果我们同时处理二者最高位\(1\),那么\(y > x\)不符合操作条件。

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
typedef double db;
#define fi first
#define se second
using i128 = __int128_t;
using piii = pair<ll, pair<ll, ll>>;

ll lowbit(ll x)
{
    return x & -x;
}

void solve()
{
    ll n, m;
    cin >> n >> m;
    if ((n ^ m) < n)
    {
        cout << 1 << endl;
        cout << n << ' ' << m << endl;
        return;
    }
    vector<ll> ans;
    ans.emplace_back(n);
    ll x = n;
    vector<ll> b;
    for (int i = 62; i >= 0; i--)
    {
        if (x >> i & 1)
        {
            b.emplace_back(i);
        }
        if (m >> i & 1)
        {
            if (b.size() <= 1)
            {
                puts("-1");
                return;
            }
            auto t = b.back();
            b.pop_back();
            ll val = (1ll << t) - 1;
            for (auto a : b)
            {
                val += (1ll << a);
            }
            ans.emplace_back(val);
            ans.emplace_back(m);
            break;
        }
    }
    cout << ans.size() - 1 << endl;
    for (auto x : ans)
    {
        cout << x << ' ';
    }
    cout << endl;
}

int main()
{
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}
posted @ 2024-03-02 01:09  value0  阅读(269)  评论(0)    收藏  举报