第十二届蓝桥杯省赛大学A组C++异或数列

本文借鉴了蓝桥杯2021年第十二届省赛-异或数列_异或后若小于原先数则输出0,大于则输出1-优快云博客的思路,记录了自己对一些难点的理解和概括,侵删 

思路

  1. 异或,每一位单独考虑。0异或上谁都不变,1异或上谁取反
  2. 判胜负就是看谁的最高位1更高
  3. 对于一位,如果有偶数个1——最后二人的值要么都是奇数个1异或的结果,要么都是偶数个1异或的结果,一定相同。
  4. 如果有奇数个1                                                                                                                        

①如果只有一个1,Alice必胜

②如果总牌数为奇数:Alice拿1与自己异或,处于胜态(1,0),剩下偶数个1、0,且Alice成为后手。Bob若拿1与自己异或,Alice可以拿1消灭Bob;Bob若拿1与Alice异或,Alice可以又拿1与自己异或;Bob若拿0与Alice或自己异或,Alice也拿0即可保持胜态。Alice必胜

③如果总牌数为偶数:第一轮,如果Alice拿0,Bob拿1;如果Alice拿1,Bob拿0,则Bob可以使第一轮过后的状态是(0,1)或(1,0),且剩偶数个1,偶数个0,且Bob处于后手。如果是(0,1),那么现在的Bob相当于②中处于胜态(1,0)的Alice,胜态可以保持。如果是(1,0),先举个特例:比如剩2个1,零个0,Alice虽然是胜态但只能选择用1让自己为0或让Bob为1,即变为(1,1)或(0,0),Bob用最后一个1就可以让状态变成(0,1)。偶数个1,偶数个0其实同理,因为Alice取0后Bob跟随取0,那么最后0就是零个;偶数个1相当于2个1的重复。Bob必胜

代码

统计二进制下每一位的1的个数,然后从高位遍历下去判胜负。(蓝桥云课题目里的0≤Xi​<20^20应为2^20) 

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;
const int N = 1e6 + 1;
int cnt1[21];

void add_cnt(int x) {
    int k = 1;
    while (x) {
        if (x & 1) cnt1[k]++;
        x >>= 1;
        k++;
    }
}

int main()
{
    IOS;
    int t;
    cin >> t;
    while (t--) {
        memset(cnt1, 0, sizeof(cnt1));
        int n, x;
        cin >> n;
        for (int i = 1; i <= n; i++) {
            cin >> x;
            add_cnt(x);
        }
        int i;
        for (i = 20; i > 0; i--) {
            if (cnt1[i]&1) {
                if (cnt1[i] == 1||n&1) cout << 1 << endl;
                else cout << -1 << endl;
                break;
            }
        }
        if (i == 0) cout << 0 << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值