加与乘(博弈论)

problem

A , B A,B A,B 在玩游戏,给定一排长度为 n n n 的数列,每个人轮流取出任意一对相邻的两个数,然后把两个数的和或者乘积放入。

T T T 组询问。每组给定 n , m n,m n,m,接下来给定长度为 n n n 的数列 a i a_i ai

m = 0 m=0 m=0 A A A 先操作, m = 1 m=1 m=1 B B B 先操作,如果最后剩下的一个数为偶数则 A A A 获胜,否则 B B B 获胜。

两人均采用最优策略。

n ≤ 1 e 5 , T ≤ 10 n\le 1e5,T\le 10 n1e5,T10

solution

observation1 : \text{observation1}: observation1: 整个过程只与 a i a_i ai 的奇偶有关。

observation2 : \text{observation2}: observation2: 无论是一奇一偶 / 两奇 / 两偶, A A A 都有一种方式将这个两个数取出后放入一个偶数进去。

observation3 : \text{observation3}: observation3: 基于前一个观察,可知如果最后一次操作的人是 A A A,那么他一定获胜。

observation4 : \text{observation4}: observation4: A A A 一定想尽可能扔掉奇数加入偶数, B B B 一定想尽可能扔掉偶数加入奇数。

对于 A A A 不管相邻两个数的各自奇偶情况,最后一定都会选择放回去一个偶数。

对于 B B B 而言,两偶怎么操作都是偶,两奇必须乘操作才是奇,一奇一偶怎么操作都是奇。

observation5 : \text{observation5}: observation5: 无论 B B B 怎么操作都不可能增加原有的奇数个数,最多保持不变。

贪心地, A A A 如果能在自己游戏轮数内将所有的奇数都扔完则必胜。

而他肯定选择一段连续的奇数操作是最有效的。

B B B 是尽量操作一奇一偶局面或者两偶局面,这样才能保证奇数个数不减少。

具体看下代码就能懂了。

code

#include <bits/stdc++.h>
using namespace std;
#define maxn 100005
int T, n, m;
int a[maxn];

int main() {
    scanf( "%d", &T );
    while( T -- ) {
        scanf( "%d %d", &n, &m );
        for( int i = 1;i <= n;i ++ ) scanf( "%d", &a[i] ), a[i] &= 1;
        if( (n - 1 & 1) ^ (m & 1) ) { puts("A"); continue; }
        int ans = 0;
        for( int i = 1;i <= n;i ++ )
            if( a[i] > a[i - 1] ) {
                int j = i;
                while( j <= n and a[j] ) j ++;
                ans += j - i + 1 >> 1;
                i = j - 1;
            }
        if( ans <= (n - m >> 1) ) puts("A");
        else puts("B");
    }
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值