• [AtCoderContest010D]Decrementing


    [AtCoderContest010D]Decrementing

    试题描述

    There are (N) integers written on a blackboard. The (i)-th integer is (A_i), and the greatest common divisor of these integers is (1).

    Takahashi and Aoki will play a game using these integers. In this game, starting from Takahashi the two player alternately perform the following operation:

    • Select one integer on the blackboard that is not less than (2), and subtract (1) from the integer.

    • Then, divide all the integers on the black board by (g), where (g) is the greatest common divisor of the integers written on the blackboard.

    • The player who is left with only (1)s on the blackboard and thus cannot perform the operation, loses the game. Assuming that both players play optimally, determine the winner of the game.

    两个人玩游戏,他们轮流操作一个初始时最大公约数为 (1) 的序列,一次操作是将一个数减 (1),然后所有数除以它们的最大公约数,最终无法操作者输,问是否先手必胜。

    输入

    The input is given from Standard Input in the following format:

    N
    A_1 A_2 … A_N
    

    输出

    If Takahashi will win, print First. If Aoki will win, print Second.

    输入示例1

    3
    3 6 7
    

    输出示例1

    First
    

    输入示例2

    4
    1 2 4 8
    

    输出示例2

    First
    

    输入示例3

    5
    7 8 8 8 8
    

    输出示例3

    Second
    

    数据规模及约定

    (1 le N le 10^5)

    (1 le Ai le 10^9)

    The greatest common divisor of the integers from (A_1) through (A_N) is (1).

    题解

    可能考虑奇偶性是一类博弈问题的思路吧。

    首先,如果开始时全是奇数,注意到每次操作不会改变数的奇偶性,所以先手一定会将一个奇数变成偶数,那么后手就可以将这个偶数变回奇数,直到最终都变成了 (1)(全是奇数),所以后手必胜。

    类似地,可以推广出:奇数个偶数,先手必胜;偶数个偶数,后手必胜。

    但是有一个小 bug,如果开始时只有一个奇数,那么就不一定了,因为先手可能将那个奇数变成偶数,然后除以一下公约数,变成一个新局面。

    当然这种情况很好处理,直接暴力模拟,直到“只有一个奇数”的局面消失,或者变成了全 (1) 序列,模拟次数不会超过 (log_2max{A_i})

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 100010
    
    int n, ceven, A[maxn];
    
    int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
    
    int main() {
    	int sum = 0; bool has1 = 0, cur = 0;
    	n = read();
    	for(int i = 1; i <= n; i++) A[i] = read(), ceven += !(A[i] & 1), has1 |= (A[i] == 1), (sum += A[i] - 1) &= 1;
    	
    	if(has1) return puts(sum ? "First" : "Second"), 0;
    	if(ceven & 1) return puts("First"), 0;
    	if(n - ceven > 1) return puts("Second"), 0;
    	for(; ;) {
    		cur ^= 1;
    		for(int i = 1; i <= n; i++) if(A[i] & 1) A[i]--;
    		int g = A[1];
    		for(int i = 2; i <= n; i++) g = gcd(g, A[i]);
    		ceven = sum = has1 = 0;
    		for(int i = 1; i <= n; i++) A[i] /= g, ceven += !(A[i] & 1), has1 |= (A[i] == 1), (sum += A[i] - 1) &= 1;
    		if(has1) return puts((sum ^ cur) ? "First" : "Second"), 0;
    		if(n - ceven > 1) return puts(((ceven & 1) ^ cur) ? "First" : "Second"), 0;
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    Quartz.NET-2.3.3 各种 数据库配置 类别大全
    C#获取当前路径的七种方法 【转载】
    BCB 如何拦截TAB键消息
    用union 和 struct 位域操作
    表值函数
    C#中 委托和事件的关系
    关于C++ Builder Codegurad 问题的排查。
    存储过程中使用事务的“正规”写法
    C++ 中对vector<T*> 数组的查找和排序
    BCB 中 Application->CreateForm 和 New 的一个区别
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/7739405.html
Copyright © 2020-2023  润新知