zoukankan      html  css  js  c++  java
  • CF1382B

    先特判所有数都为 (1) 或都不为 (1) 的情况。

    • 所有数都为 (1):判断奇偶性;
    • 所有数都不为 (1):先手必胜,原因略。

    对于其余情况,正难则反。
    ( ext{flag}_i=1/2) 为取走第 (i) 堆中的最后一个石头的人(取完石头)的编号。

    例如,若第 (2) 堆中有 (3) 个石头,1 取走前 (2) 个,2 取走最后 (1) 个,则 ( ext{flag}_2= extbf{2})

    假设 ( ext{flag}_n=1),即 1 获胜。
    枚举 (i=n-1,n-2,cdots,1)。分类讨论:

    • ( ext{flag}_{i+1}=1)
      • (a_i=1),即第 (i) 堆中有 (1) 个石头且第 ((i+1)) 堆被 1 取完,则第 (i) 堆必然被 2 取完。原因略;
      • (a_i>1),即第 (i) 堆中有多于 (1) 个石头且第 ((i+1)) 堆被 1 取完,则第 (i) 堆必然被 1 取完。因为若第 (i) 堆被 2 取完,则 2 在取第 (i) 堆的时候会取 ((a_i-1)) 个石头,而留下 (1) 个石头给 1 取走。这样先后手关系便和假设矛盾,胜负也随之逆转。所以第 (i) 堆不可能被 2 取完。
    • ( ext{flag}_{i+1}=2),即第 ((i+1)) 堆被 2 取完,则第 (i) 堆必然被 1 取完。因为若第 (i) 堆被 2 取完,则 2 会取走 (a_i) 个(即取完第 (i) 堆),让先后手关系逆转。

    枚举过后检查 ( ext{flag}_1) 是否为 (1) 即得到答案(通过判断与假设是否矛盾,得到答案)。
    时间复杂度线性。
    Code:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxN=100005;
    int flag[maxN];
    int main() {
    	int t; scanf("%d",&t);
    for (;t;t--) {
    	int n; scanf("%d",&n);
    	vector<int> a(n+1);
    	int one=0;
    	for (int i=1;i<=n;i++) {
    		scanf("%d",&a[i]);
    		if (a[i]==1) one++;
    	}
    	if (!one) puts("First");
    	else if (one==n) puts(n&1?"First":"Second");
    	else {
    		flag[n]=1;
    		for (int i=n-1;i;i--)
    			if (flag[i+1]==1)
    				if (a[i]==1) flag[i]=2;
    				else flag[i]=1;
    			else flag[i]=1;
    		puts(flag[1]==1?"First":"Second");
    	}
    }
    }
    
  • 相关阅读:
    大咖们如何评判优秀架构师?
    腾讯会议大规模任务调度系统架构设计
    计算压力倍增,携程度假起价引擎架构演变
    快手春节红包背后,高并发存储架构设计
    日均20亿流量:携程机票查询系统的架构升级
    我是如何一步步的在并行编程中将lock锁次数降到最低实现无锁编程
    OGRE
    CMake
    深入理解C++11【5】
    深入理解C++11【4】
  • 原文地址:https://www.cnblogs.com/Xray-luogu/p/13368926.html
Copyright © 2011-2022 走看看