Codeforces Round 960 (Div. 2)题解(待完成)

锐评

菜就多练好吧,第二题思路想到了没码出来,C题没看明白:=是什么意思。A题还WA一发。

A. Submission Bait

题意

爱丽丝和鲍勃在大小为 n n n 的数组 a a a 中进行游戏。

他们轮流进行运算,爱丽丝先开始。不会运算的一方将输掉比赛。一开始,变量 m m m x x x 被设置为 0 0 0

在一次操作中,玩家可以

  • 选择 i i i$ ( 1≤i≤n )$这样的索引 a i ≥ m x ai≥mx aimx ,并将 m x mx mx 设置为 a i ai ai。然后将 a i ai ai 设为 0 0 0

判断爱丽丝是否有一个获胜的策略。

输入描述

  • 第一行包含一个整数 t t t ( 1 ≤ t ≤ 1 0 3 1 \leq t \leq 10^3 1t103) - 测试用例的数量。

对于每个具体的测试用例:

  • 第一行包含一个整数 n n n ( 2 ≤ n ≤ 50 2 \leq n \leq 50 2n50) - 数组的大小。
  • 第二行包含 n n n 个整数 a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,,an ( 1 ≤ a i ≤ n 1 \leq a_i \leq n 1ain) - 数组的元素。

样例输入

5
2
2 1
2
1 1
3
3 3 3
4
3 3 4 4
4
1 2 2 2

样例输出

YES
NO
YES
NO
YES

样例说明

在第一个测试案例中,爱丽丝可以选择 i = 1 i=1 i=1 ,因为 a 1 = 2 ≥ m x = 0 a_1=2 \ge mx=0 a1=2mx=0

爱丽丝操作后, a = [ 0 , 1 ] a=[0,1] a=[0,1] m x = 2 mx=2 mx=2 。鲍勃无法进行任何操作。爱丽丝获胜。

在第二个测试案例中,爱丽丝没有获胜策略。

例如,如果爱丽丝选择 i = 1 i=1 i=1 ,那么在爱丽丝的操作之后, a = [ 0 , 1 ] a=[0,1] a=[0,1] m x = 1 mx=1 mx=1 a = [ 0 , 1 ] a=[0,1] a=[0,1] m x = 1 mx=1 mx=1 。那么,由于 a 2 = 1 ≥ m x = 1 a_2=1 \ge mx=1 a2=1mx=1 ,鲍勃可以选择 i = 2 i=2 i=2 。鲍勃操作后 a = [ 0 , 0 ] a=[0,0] a=[0,0] m x = 1 mx=1 mx=1 。爱丽丝无法进行任何操作。鲍勃获胜。

思路

可以得到如果A直接选最大的,只要最大的数量是奇数就可以,我就是这么WA的,忽略了A可以选别的来增加她的胜算。对于每一个数出现的次数,实际上奇数是对Alice有利的,从后向前找第一个数只出现了奇数次,只要能找到那么就能赢,否则就不能,也就是看有没有数出现了奇数次。


#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e6 + 9;
#define int long long
const int MOD = 998244353;
int qmi(int a, int b, int p) {
	int res = 1;
	while (b) {
		if (b & 1) res = res * a % p;
		a = a * a % p;
		b >>= 1;
	}
	return res;
}
int inv(int x) {return qmi(x, MOD - 2, MOD);}

int gcd(int a, int b) {return b > 0 ? gcd(b, a % b) : a;}
int lcm(int a, int b) {return a / gcd(a, b) * b;}

int n, a[N], cnt[N];

void solve() {
	cin >>n;
    for (int i = 1; i <= n; ++ i) cin >> a[i];
    sort(a + 1, a + 1 + n);
    map<int,int>mp;
    for (int i = n; i >= 1; -- i) {
        mp[a[i]] ++;
    }
    for (auto i : mp) {
        if (i.first && i.second % 2 == 1) {
            cout << "YES\n";
            return;
        }
    }
    cout << "NO\n";
}

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

B. Array Craft

题意

对于大小为 m m m 的数组 b b b ,我们可以这样定义:

  • b b b最大前缀位置是满足 b 1 + … + b i = max ⁡ j = 1 m ( b 1 + … + b j ) b_1+\ldots+b_i=\max_{j=1}^{m}(b_1+\ldots+b_j) b1++bi=maxj=1m(b1++bj)最小索引 i i i
  • b b b最大后缀位置是满足 b i + … + b m = max ⁡ j = 1 m ( b j + … + b m ) b_i+\ldots+b_m=\max_{j=1}^{m}(b_j+\ldots+b_m) bi++bm=maxj=1m(bj++bm)索引 i i i

给你三个整数 n n n x x x y y y ( x > y x > y x>y )。请构造一个大小为 n n n 的数组 a a a 以满足以下条件:

  • 对于所有的 1 ≤ i ≤ n 1 \le i \le n 1in a i a_i ai 要么是 1 1 1 要么是 − 1 -1 1
  • a a a最大前缀位置 x x x
  • a a a最大后缀位置 y y y

如果有多个数组满足条件,则打印任意一个。可以证明,在给定的条件下,这样的数组总是存在的。

输入描述

第一行包含一个整数 t t t 1 ≤ t ≤ 1 0 4 1 \leq t \leq 10^4 1t104),表示测试用例的数量。

对于每个测试用例:

  • 只有一行,该行包含三个整数 n n n x x x y y y(满足 2 ≤ n ≤ 1 0 5 2 \leq n \leq 10^5 2n105 以及 1 ≤ y < x ≤ n 1 \leq y < x \leq n 1y<xn)。

确保所有测试用例中所有 n n n 的总和不超过 1 0 5 10^5 105

样例输入

3
2 2 1
4 4 3
6 5 1

样例输出

1 1
1 -1 1 1
1 1 -1 1 1 -1

思路

实际上这个题最开始想的是对的,后面不知道怎么又想到全 − 1 -1 1 1 1 1 了,再后面发现了就摆了,因为我构造的还挺麻烦的分了好几步,所以也没做出来,实际上我们可以得知y一定是小于 x x x,(这是给的条件,当时我就没看到qwq)因此 x x x y y y 之间包含的公共部分自然是越大越好,两边是越小越好,只有这样才能将端点约束在 x x x y y y

在这里插入图片描述

  • x x x 之所以没有停留在绿色部分是因为即使加上绿色部分红色部分对它的好处更大。
  • 而没有继续相见走是因为后面的过程中没有一个是让它更大的。
  • 因此 x x x向后的第一个元素肯定是 − 1 -1 1, 当然也不是越小越好,要不然如果绿色太低,即使加上红色也不能回正,还不如只要一个 − 1 -1 1
  • 因此绿色部分尽量趋近于零即可,这样满足了所有要求,即 − 1 -1 1 1 1 1来回交替。

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e6 + 9;
#define int long long
const int MOD = 998244353;
int qmi(int a, int b, int p) {
	int res = 1;
	while (b) {
		if (b & 1) res = res * a % p;
		a = a * a % p;
		b >>= 1;
	}
	return res;
}
int inv(int x) {return qmi(x, MOD - 2, MOD);}

int gcd(int a, int b) {return b > 0 ? gcd(b, a % b) : a;}
int lcm(int a, int b) {return a / gcd(a, b) * b;}

int n, a;

void solve() {
	cin >> n;
    int x, y;
    cin >> x >> y;
    for (int i = 1; i <= n; ++ i) {
        if (i < y) a = (y - i) & 1 ? -1 : 1;
        else if (i <= x) a = 1;
        else {
            a = (i - x) & 1 ? -1 : 1;
        }
        cout << a << " ";
    }
    cout << "\n";
}

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

C. Mad MAD Sum

待补

  • 11
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值