[Codeforce刷题8]

A. 决斗时刻到了

https://codeforces.com/contest/2109/problem/A

时间限制: 1 秒
内存限制: 256 兆字节
输入: 标准输入
输出: 标准输出

关于 Mouf,你可能不知道他是游戏王卡牌游戏的忠实粉丝。他喜欢和任何人决斗。为了召集所有喜欢玩游戏的粉丝,他决定组织一次大型游戏王锦标赛,并邀请了 n n n 名玩家参加。

Mouf 将 n n n 名玩家排成一排,从 1 1 1 n n n 依次编号。然后他们连续进行了 n − 1 n - 1 n1 次对决:从 1 1 1 n − 1 n - 1 n1 的每一个 i i i,棋手 i i i 对阵棋手 i + 1 i + 1 i+1,每场比赛产生一个赢家和一个输家。之后,每个棋手都会报告一个值 a i a_i ai ( 0 ≤ a i ≤ 1 0 \le a_i \le 1 0ai1):

  • 0 0 0 表示他们没有赢得决斗;
  • 1 1 1 表示他们至少赢了一场决斗。

由于有些人可能会谎报自己的结果(例如,报告的是 1 1 1 而不是 0 0 0,反之亦然)以影响奖金结果,因此如果穆夫能证明任何报告是假的,他就会取消比赛。

给定数组 a a a,判断是否至少有一名棋手在说谎。

输入

每个测试包含多个测试用例。第一行包含测试用例的数量 t t t ( 1 ≤ t ≤ 100 1 \le t \le 100 1t100)。测试用例说明如下。

每个测试用例的第一行都包含一个整数 n n n ( 2 ≤ n ≤ 100 2 \le n \le 100 2n100) - 锦标赛的参赛人数。

每个测试用例的第二行包含 n n n 个整数 a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,,an ( 0 ≤ a i ≤ 1 0 \le a_i \le 1 0ai1) --表示 i i i-th 玩家的报告。

输出

对于每个测试用例,如果参与者中至少有一个说谎者,则打印 “是”(不带引号),否则打印 “否”(不带引号)。

您可以用任何大小写(大写或小写)输出答案。例如,字符串 “yEs”、“yes”、"Yes "和 "YES "将被识别为肯定回答。

解题思路

这道题目需要判断玩家是否在报告比赛结果时撒谎。关键点在于:

  1. 每个玩家要与相邻的玩家比赛一次
  2. 如果一个玩家报告0,表示他没赢过任何比赛
  3. 如果一个玩家报告1,表示他至少赢过一次比赛

判断逻辑

  1. 如果所有玩家都报告1,一定有人撒谎(因为不可能没有人输)
  2. 如果所有玩家都报告0,同样明显撒谎(因为一定有赢家)
  3. 如果有两个相邻的玩家都报告0,那么至少有一人在撒谎(因为他们必须对战,必有一人获胜)
  4. 若上述条件都不满足,则存在一种排列使得报告是真实的
AC Code
#include <bits/stdc++.h>
using namespace std;

void solve() {
    int n;
    cin >> n;
    vector<int> a(n);
    int cnt1 = 0, cnt2 = 0;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        if (a[i] == 1) {
            cnt1++;
        } else {
            cnt2++;
        }
    }
    if (cnt1 == 0 || cnt2 == 0) {
        cout << "YES" << endl;
        return;
    }
    for (int i = 0; i < n - 1; ++i) {
        if (a[i] == 0 && a[i + 1] == 0) {
            cout << "YES" << endl;
            return;
        }
    }
    cout << "NO" << endl;
}
  
int main() {
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);

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

B. 切片生存

https://codeforces.com/contest/2109/problem/B

时间限制: 1 秒
内存限制: 256 兆字节
输入: 标准输入
输出: 标准输出

决斗者 Mouf 和 Fouad 进入竞技场,这是一个 n × m n \times m n×m 格!

法德的怪物从 ( a , b ) (a, b) (a,b) 单元格开始,其中行的编号为 1 1 1 n n n,列的编号为 1 1 1 m m m

毛夫和法德将一直对决,直到网格中只剩下一个单元格。

在每个回合中:

  • 穆夫首先沿着一行或一列将网格切成两部分,然后丢弃没有法德怪物的部分。注意,网格必须至少有两个单元格,否则游戏已经结束。
  • 然后,在同一回合中,法德将他的怪物移动到剩余网格中的任何一个单元格(可能是它原来所在的单元格)。


第四个测试案例的可视化阶段。

穆夫希望尽量减少回合数,而法德则希望尽量增加回合数。如果双方都发挥出最佳水平,这场史诗般的对决将持续多少回合?

输入

每个测试包含多个测试用例。第一行包含测试用例的数量 t t t ( 1 ≤ t ≤ 1 0 4 1 \le t \le 10^4 1t104)。测试用例说明如下。

每个测试用例的第一行也是唯一一行包含四个整数 n n n m m m a a a b b b ( 2 ≤ n , m ≤ 1 0 9 2 \le n, m \le 10^9 2n,m109 1 ≤ a ≤ n 1 \le a \le n 1an 1 ≤ b ≤ m 1 \le b \le m 1bm),分别表示行数、列数、怪物的起始行和怪物的起始列。

输出

对于每个测试用例,输出一个整数——如果双方都发挥出最佳水平,这场史诗对决将持续的回合数。

解题思路

我们需要模拟网格被逐步分割的过程,计算出最优策略下的回合数。

分析

问题分解
  • 每次切割将网格分成两部分,保留包含怪物的部分。
  • 玩家会移动怪物到剩余网格的任意位置,以最大化回合数。
最优策略
  • 穆夫希望最小化回合数,因此每次切割应尽可能将网格分成较小的部分。
  • 法德希望最大化回合数,因此会移动怪物到剩余部分中间位置。
模拟过程
  • 计算每次切割后网格的大小,并记录切割次数。
  • 使用递归或循环模拟切割过程,直到网格缩小到 1x1。
算法步骤
  1. 计算在行和列方向上的最佳切割策略(因为初始时需要根据怪物的位置进行切割,之后的切割怪物可以随意移动,只需要一开始时考虑即可)。
  2. 分别计算从行和列开始的最佳切割次数
  3. 取这两个方向中的最小值作为最终结果
AC Code
#include <bits/stdc++.h>
using namespace std;
  
typedef long long ll;
  
ll cal(ll r, ll c) {
    ll res = 0;
    while (r > 1 || c > 1) {
        res++;
        if (r == 1) {
            c = (c + 1) / 2;
        } else if (c == 1) {
            r = (r + 1) / 2;
        } else {
            if (r >= c) {
                r = (r + 1) / 2;
            } else {
                c = (c + 1) / 2;
            }
        }
    }
    return res;
}

void solve() {
    ll n, m, a, b;
    cin >> n >> m >> a >> b;

    ll row = min(a, n - a + 1);
    ll row1 = 1 + cal(row, m);

    ll col = min(b, m - b + 1);
    ll col1 = 1 + cal(n, col);

    cout << min(row1, col1) << "\n";
}

int main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Almond_s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值