Codeforces Round 919 (Div. 2)

Codeforces Round 919 (Div. 2)

A. Satisfying Constraints

解题思路:

确定最大下界和最小上界。

然后看有多少个不可选数在界内。

代码:

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

void solve()
{
    int n;
    cin >> n;
    ll l = 0;
    ll r = 1e18;
    vector<ll> v;
    for (int i = 1; i <= n; i++)
    {
        int t = 1;
        ll x;
        cin >> t >> x;
        if (t == 1)
        {
            l = max(l, x);
        }
        else if (t == 2)
        {
            r = min(r, x);
        }
        else
        {
            v.push_back(x);
        }
    }
    sort(v.begin(), v.end());
    int cnt = 0;
    for (auto x : v)
    {
        if (x >= l && x <= r)
        {
            cnt++;
        }
    }
    cout << max(0ll, r - l + 1 - cnt) << endl;
}

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

B. Summation Game

解题思路:

枚举爱丽丝删最后\(0个,1个,...k个\)

鲍勃总是将最大的\(x\)个变负。

代码:

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

void solve()
{
    int n;
    cin >> n;
    int k, x;
    cin >> k >> x;
    vector<ll> a(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    sort(a.begin() + 1, a.end());
    for (int i = 1; i <= n; i++)
    {
        a[i] += a[i - 1];
    }
    ll ans = -1e18;
    for (int i = n; i >= n - k; i--)
    {
        ll l = max(1, i - x + 1);
        ans = max(ans, a[n] - (a[n] - a[i]) - 2 * (a[i] - a[l - 1]));
    }
    cout << ans << endl;
}

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

C. Partitioning the Array

解题思路:

预处理出所有因子。

遍历因子。

对于每个因子\(p\),搜前\(p\)个,然后每个跳\(p\)搜。(就是搜每个子数组第一个,然后搜每个子数组第二个。。。)这样的顺序搜索数组每个元素。

若所有子数组对应位置之差的最大公因数不为\(1\),则分数加一。

举例:

\([1,2],[3,4],[5,6]\)

上述情况的差数有\(3 - 1= 2,5 - 3 = 2,4 - 2 = 2,6 - 4= 4.(2,2,2,2)\).

\(求(2,2,2,2)最大公因数即可\)

代码:

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

ll gcd(ll a, ll b)
{
    return b ? gcd(b, a % b) : a;
}

void solve()
{
    int n;
    cin >> n;
    vector<int> fac;

    for (int i = 1; i <= n / i; i++)
    {
        if (n % i == 0)
        {
            fac.push_back(i);
            if (n / i != i)
            {
                fac.push_back(n / i);
            }
        }
    }
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
    }
    // for (auto p : fac)
    // {
    //     cout << p << ' ';
    // }
    ll ans = 0;
    for (auto p : fac)
    {
        bool f = true;
        ll g = 0;
        for (int i = 1; i <= p; i++)
        {
            for (int j = i + p; j <= n; j += p)
            {
                g = gcd(g, abs(a[j] - a[j - p]));
                if (g == 1)
                {
                    // cout << p << ' ' << j << endl;
                    f = false;
                    break;
                }
            }
            if (!f)
            {
                break;
            }
        }
        if (f)
        {
            // cout << g << endl;
            ans++;
        }
    }
    printf("%lld\n", ans);
}

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

D. Array Repetition

解题思路:

只有单独插入的数需要记录位置。

翻倍添加的数模上翻倍时原序列的长度,一定会对应上原序列的某个数的位置。

如果原位置是插入的数,直接取出记录的数。

否则,继续往前模。每次模完长度至少减半,所以时间复杂度可过。

代码:

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

void solve()
{
    ll n, q;
    cin >> n >> q;
    vector<pii> v;
    map<ll, ll> mp;
    i128 len = 0;
    for (int i = 1; i <= n; i++)
    {
        int t, x;
        scanf("%d %d", &t, &x);
        if (t == 1)
        {
            len = len + 1;
            mp[(ll)len] = x;
        }
        else
        {
            if (len > 1e18)
            {
                continue;
            }
            ll t = 0;
            if (len <= 1e18)
            {
                t = len;
                len = len * (x + 1);
            }
            if (len > 1e18)
            {
                len = 1e18 + 1;
            }
            v.push_back({len, t});
        }
    }
    sort(v.begin(), v.end());
    // for (auto x : v)
    // {
    //     cout << x.fi << ' ' << x.se << endl;
    // }
    while (q--)
    {
        ll x = 0;
        scanf("%lld ", &x);
        while (!mp.count(x))
        {
            auto it = lower_bound(v.begin(), v.end(), (pii){x, 0ll});
            ll len = (*it).se;
            x %= len;
            if (x == 0)
            {
                x = len;
            }
        }
        printf("%lld ", mp[x]);
    }
    cout << endl;
}

int main()
{
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}
posted @ 2024-01-14 00:53  value0  阅读(187)  评论(0)    收藏  举报