agc009d

D - Decrementing

Time limit : 2sec / Memory limit : 256MB

Score : 1000 points

Problem Statement

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 1s on the blackboard and thus cannot perform the operation, loses the game. Assuming that both players play optimally, determine the winner of the game.

Constraints

  • 1≦N≦105
  • 1≦A**i≦109
  • The greatest common divisor of the integers from A1 through A**N is 1.

Solution

唯一确定的先手必胜态为{1,1,1,1,...,2}看出这种状态的基本特征—元素为偶数的个数为奇数。

分类讨论:

  • 偶数有奇数个时,只要保证gcd不为偶数则能保证当前奇偶状态不会发生改变(即保持奇数的个数不为1)

  • 偶数有偶数个时,奇数的个数一定为1时才能逆转奇偶状态,递归解决即可。
    复杂度 因为最差情况下都会除以不为1的gcd,所以最多操作log2(min{a[i]})次

    所以最后总复杂度为O(nlog2(min{a[i]}))

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
inline int read() {
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9') f=(ch=='-')?-1:1,ch=getchar();
	while(ch>='0'&&ch<='9') x=10*x+(ch-'0'),ch=getchar();return x;
}
const int N=1e5+50;
int a[N],n,s0,s1;
int gcd(int x,int y) {return !y?x:gcd(y,x%y);}
bool dfs(int x) {
	int sum=0,flag=0;
	fo(i,1,n) if(a[i]%2) {a[i]--;break;}
	int g=a[1];
	fo(i,2,n) g=gcd(g,a[i]);
	fo(i,1,n)  {
		a[i]/=g;
		if(a[i]%2==0) sum++;
		if(a[i]==1) flag=1;
	}
	if(sum%2) return x^1;
	if(flag||n-sum!=1) return x;
	return dfs(x^1);
}
int main() {
	freopen("1.in","r",stdin);
	bool flag=0;
	n=read();
	fo(i,1,n) {
		a[i]=read(),(a[i]%2)?s1++:s0++;
		if(a[i]==1) flag=1;
	}
	if(s0%2) printf("First
");
	else {
		if(flag||s1!=1) printf("Second
");
		else if(dfs(1)) printf("First
");
		else printf("Second
");
	}
	return 0;
} 
原文地址:https://www.cnblogs.com/patricksu/p/8485930.html