Codeforces Round 902 (Div. 2, based on COMPFEST 15 - Final

发布时间 2023-10-09 17:11:13作者: value0

Codeforces Round 902 (Div. 2, based on COMPFEST 15 - Final

A. Goals of Victory

解题思路:

答案为所有元素之和的负数。

代码:

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

void solve()
{
    int n;
    cin >> n;
    ll res = 0;
    for (int i = 1; i < n; i++)
    {
        int x;
        cin >> x;
        res += x;
    }
    cout << -res << endl;
}

int main()
{
    int t = 1;
    scanf("%d", &t);
    while (t--)
    {
        solve();
    }
    return 0;
}

B. Helmets in Night Light

解题思路:

开头我们通知一个\(b_i\)最小的村名,接下来贪心每次都通知花费最小的村民,如果此时花费最小的村民的花费大于\(p\),那么剩下的都亲自通知。

代码:

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

void solve()
{
    int n, p;
    scanf("%d %d", &n, &p);
    vector<pll> v(n + 1);
    for (int i = 1; i <= n; i++)
    {
        scanf("%lld", &v[i].se);
    }
    for (int i = 1; i <= n; i++)
    {
        scanf("%lld", &v[i].fi);
    }
    sort(v.begin() + 1, v.end());
    ll res = p;
    ll cnt = 1;
    for (int i = 1; i <= n; i++)
    {
        if (v[i].fi > p)
        {
            break;
        }
        ll t = min(v[i].se, n - cnt);
        v[i].se -= t;
        cnt += t;
        res += t * v[i].fi;
        if (cnt == n)
        {
            break;
        }
    }
    res += (n - cnt) * (ll)p;
    printf("%lld\n", res);
}

int main()
{
    int t = 1;
    scanf("%d", &t);
    while (t--)
    {
        solve();
    }
    return 0;
}

C. Joyboard

解题思路:

从后往前,最终\(a_i\)一定会除以\(1\)变成\(0\)

所以如果\(k = 1\),那么\(a_{n + 1} = 0\)。答案唯一。

如果\(k = 2\),那么除了\(0\)只能出现一个数字。

  • \(a_{n + 1} \geq n\),一定要是\(a_{n + 1} \% \ n = 0\),如果不为\(0\)一定出现至少三个不同的数。
  • \(0<a_{n + 1} < n\),一定刚好出现两个数。

如果\(k =3\),那么\(k = 1,k = 2\)的情况去掉,就是答案。

否则,答案为\(0\)。因为如果\(a_{n + 1} < n\),要么除完一次就变\(0\),要么开始就是\(0\),最多出现两个不同数。

如果\(a_{n + 1}\geq n\),要么\(a_{n + 1} = kn\),除完一次就成0,要么除完一次后\(a_n < n\),如上,最多再除一次就会变成\(0\)。所以最多三次。

代码:

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

void solve()
{
    int n, k, m;
    scanf("%d %d %d", &n, &m, &k);
    if (k == 1)
    {
        printf("1\n");
    }
    else if (k == 2)
    {
        ll res = (min(n, m)) + (m > n ? m / n - 1 : 0);
        printf("%lld\n", res);
    }
    else if (k == 3)
    {
        ll res = (min(n, m)) + (m > n ? m / n - 1 : 0);
        res = m - res - 1 + 1;
        printf("%lld\n", res);
    }
    else
    {
        printf("0\n");
    }
}

int main()
{
    int t = 1;
    scanf("%d", &t);
    while (t--)
    {
        solve();
    }
    return 0;
}

D. Effects of Anti Pimples

解题思路:

我们通过枚举确定,如果单选\(a_i\),得到的最大值\(ma_i\)是多少。

然后将这些最大值进行排序。对于\(ma_i\),如果\(ma_j < ma_i\),对答案最大值无影响,所以随便选或不选,方案数为\(2^{i-1}\)。后面大的\(ma_k > ma_i\),选了就不是\(ma_i\)为最大值做贡献了。所以,这里是\(ma_i\)对全局答案做出的贡献。

这里有个问题,如果有多个\(ma_i\)怎么办,即多个位置的最大值贡献一样怎么办?

举例:\(2,2\).答案为\(6\)

如果说,我们只选择比当前值小的,样例中也就是\(2个2^0 * 2\),那么最终答案为\(4\),是错误的。因为少算了两个都选的情况。

如果说,我们把小于等于当前值的全都是选或者不选(不包括自己,因为自己必选,没有两种可能),那么就是\(ans = 2 * (2^1 * 2) = 8\),答案偏大,因为两个都选只有一次。

我们假设这里有三个一样的值,那么选或不选的方案数有\(2^3 = 8\)种。去掉都不选的情况,一共有\(7\)种。

\(2^0 + 2^1 + 2^2 = 7\). 以下选为\(1\),反之为\(0\)\(?\)为可选可不选。

\(2^0 : 100\)

\(2^1:?10\)

\(2^2:??1\)

如上,其实顺着遍历过去,前面的都视为可选可不选即可。

\(10\),可以看为左侧选右侧不选,那么每对\((i,j)\)之间一共只有四种情况\(00,01,10,11\),本题中不能都不选,所以只有三种情况\(01,10,11\),那么如果\(10\)方案有了,剩下的就是\(01,11\),即后一位必选,前一位随意,符合上述思路。

代码:

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

ll qmi(ll a, ll b)
{
    ll res = 1;
    while (b)
    {
        if (b & 1)
        {
            res = res * a % mod;
        }
        b >>= 1;
        a = a * a % mod;
    }
    return res;
}
void solve()
{
    int n;
    scanf("%d", &n);
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
    }
    vector<int> ma(n + 1);
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= i / j; j++)
        {
            if (i % j == 0)
            {
                ma[j] = max(ma[j], a[i]);
                ma[i / j] = max(ma[i / j], a[i]);
            }
        }
    }
    sort(ma.begin() + 1, ma.end());
    ll t = qmi(1, mod - 2);
    ll ans = 0;
    for (int i = 1; i <= n; i++)
    {
        ans = (ans + (ma[i] * t)) % mod;
        t = (t * 2) % mod;
    }
    cout << ans;
}

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