AGC010 - D: Decrementing
题意简述
给出一个n(n≤105)个数的序列a,足够聪明的AB两人轮流进行以下操作:
令一个大于1的数减1,然后所有数除以gcd{a}。
如果一个人不能操作了,那么他就输了。
输入保证所有数都是正整数并且gcd{a}=1。
分析
这是一道和奇偶性有关的题目。
很容易知道拿到1,1,1,...,1就输了,此时手里数的和sum等于n。
考虑sum奇偶性的转换关系。
或者再展开一点:
偶-奇 是必然的很好理解,重点考虑一下sum为奇数的情形。
奇(-偶)-奇 要求gcd为偶数,因为偶/奇=偶。因此原数列%2必然是000…01的形式,而我可以将其变为000…11从而形成奇-偶 。所以奇-奇 是一定条件下可选的,奇-偶 是任何条件下可行的。
由此再考虑n的奇偶性对答案的影响。
- n为偶数
能保持sum为奇数的一方一定不会输。既然sum一直是奇数,那么就一定不会得到1,1,1,...,1的状态,必胜。而因为拿到奇数的一方一定可以给对手一个偶数,而对手只能无可奈何地还你一个奇数。所以初始sum为奇数则先手必胜,否则必败。
时间复杂度为O(n)。 n为奇数
能保持sum为偶数的一方一定不会输。但是拿到偶数的一方需要保证对手不会还回来一个奇数,下面证明这一点一定可以做到。证明
首先奇数方要是想还给对手一个奇数必然要使gcd不为1,所以原数列%gcd必然是000…01的形式。再考虑这个状态是怎么达到的:
对于000…11,000…02,000…1k,000…0(k+1)这四种状态另一方都有办法规避000…01的结果。所以拿到偶数的一方一定能保证下一轮自己还是偶数。因此初始sum为偶数的话先手必胜。
时间复杂度为O(n)。但是初始sum是奇数并不意味着必败;因为此时还没有另一方的干扰,是有可能给对手一个奇数的。但是由于你可能只有极少的选择方案,这给了对手可乘之机:对手也有可能还回来一个奇数。以此循环往复,无法给对手奇数的一方会输掉游戏。
因为每次都会给所有数除以一个大于1的gcd,所以最多往复log2(min{a})次,其中每次操作的复杂度是O(n)。时间复杂度最大为O(n⋅log2(min{a}))。
总时间复杂度最大为O(n⋅log2(min{a}))。
实现
只有n,sum均为奇数时无法通过判断n和sum的奇偶性来得出答案。
计算出前缀gcdg1和后缀gcdg2,然后计算gcd{g1[i−1],a[i]−1,g2[i+1]},如果 (sum−1)/gcd 为奇数就令所有数除以gcd,然后轮到对手。若没有可能的gcd,GG。
代码
//Decrementing
#include <cstdio>
typedef long long lint;
int const N=1e5+10;
int n,a[N];
int gcd(int x,int y)
{
if(x==-1 || y==-1) return -x*y;
if(x==0) return y;
else return gcd(y%x,x);
}
int g1[N],g2[N];
int main()
{
scanf("%d",&n);
lint sum=0;
for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum+=a[i];
if(n%2==0)
{
if(sum%2==1) printf("First");
else printf("Second");
return 0;
}
if(sum%2==0) {printf("First"); return 0;}
int cur=0;
while(true)
{
bool flag=false;
sum=0;
for(int i=1;i<=n;i++) sum+=a[i];
g1[0]=-1; g2[n+1]=-1;
for(int i=2;i<=n;i++) g1[i]=gcd(g1[i-1],a[i]);
for(int i=n-1;i>=1;i--) g2[i]=gcd(g2[i+1],a[i]);
int g;
for(int i=1;i<=n&&!flag;i++)
{
if(a[i]==1) continue;
g=gcd(gcd(g1[i-1],g2[i+1]),a[i]-1);
if(((sum-1)/g)%2==1) flag=true;
}
if(flag)
for(int i=1;i<=n;i++) a[i]/=g;
else
{
if(cur==0) printf("Second");
else printf("First");
return 0;
}
cur^=1;
}
return 0;
}
注意
挺好写的,主要是思维难度高
AGC010 - D: Decrementing的更多相关文章
- 【AtCoder】AGC010
AGC010 A - Addition 如果所有数加起来是偶数那么一定可以,否则不行 #include <bits/stdc++.h> #define fi first #define s ...
- Agc010_D Decrementing
今天本人因调了上篇博客的题而脑壳不适,不想颓题,因此有了这篇博客. 但是博客毕竟得讲点什么,想想有没有什么代码短的. 哦,好像有,就Agc010_D Decrementing好了. Alice和Bob ...
- [AtCoderContest010D]Decrementing
[AtCoderContest010D]Decrementing 试题描述 There are \(N\) integers written on a blackboard. The \(i\)-th ...
- AGC010
AGC010 A [过水已隐藏] B 这题推完了还是不会/kk真的毒瘤 考虑每次会减少的总和是\(n(n+1)/2\),用原来的和除以这个可以得到操作次数\(m\)(不是整数无解) 再考虑相邻两个数\ ...
- AGC010 - C: Cleaning
原题链接 题意简述 给出一棵个节点的树,每个点有点权.每次可以选择两个叶节点并将连接它们的路径上的节点的点权-1(包括叶节点).求能否将所有节点的点权都变为0. 分析 先考虑最简单的情况.在这种情况下 ...
- AGC010 - B: Boxes
原题链接 题意简述 给出一个由个数构成的环,每次可以选择一个位置并从这个数起顺时针依次对每个数-1,-2,-3,-,-n.问能否将所有数全变为0. 分析 考虑一次操作对环带来了什么影响. (在后加一个 ...
- AGC010 - A: Addition
原题链接 题意简述 给出一个个数的数列,每次选出两个奇偶性相同的数合成一个数,问最终能否只剩下一个数. 分析 非常简单的一道题. 两个偶数可以合成一个偶数,两个奇数也能合成一个偶数.所以合并偶数时偶数 ...
- AGC 010D.Decrementing(博弈)
题目链接 \(Description\) 给定\(n\)个数\(A_i\),且这\(n\)个数的\(GCD\)为\(1\).两个人轮流进行如下操作: 选择一个\(>1\)的数使它\(-1\). ...
- 【AGC010D】Decrementing
Solution 日常博弈论做不出来. 首先,数值全部为1的局面先手必败. 在接下来的过程中,我们只关注那些大于1的数值. 按照官方题解的思路,首先想一个简化版的问题:没有除的操作,其余相同.那么局面 ...
随机推荐
- C#、Java之比较
很多人说C#是微软用来和Java抗衡的武器,因为二者在很大程度上有着惊人的相似,尽管如此,两者不同的地方也很多,所谓"于细微处见差异".那么两者的相似和区别都在什么地方呢?我们从今 ...
- 【转】三大UML建模工具Visio、Rational Rose、PowerDesign的区别
本文转自http://developer.51cto.com/art/201006/207993.htm UML建模工具相信大家有所了解,那么你对UML建模工具Visio .Rational Rose ...
- js promise看这篇就够了
一.背景 大家都知道nodejs很快,为什么会这么快呢,原因就是node采用异步回调的方式来处理需要等待的事件,使得代码会继续往下执行不用在某个地方等待着.但是也有一个不好的地方,当我们有很多回调的时 ...
- 童攀TP5企业网站实战笔记
$this->assign('data',$data) ---恢复内容开始--- return view(); 载入视图 {include file='public/head'} 包含文件 ...
- 详解spl_autoload_register() 函数(转)
原文地址:http://blog.csdn.net/panpan639944806/article/details/23192267 在了解这个函数之前先来看另一个函数:__autoload. 一._ ...
- 小白的Python之路 day5 re正则模块
re正则模块 一.概述 就其本质而言,正则表达式(或 RE)是一种小型的.高度专业化的编程语言,要讲他的具体用法要讲一本书!它内嵌在Python中,并通过 re 模块实现.你可以为想要匹配的相应字符串 ...
- 【转】C++易混知识点5:实例讲解Public Protected Private作用域,继承的区别和用意
大学生涯,涉及到类的作用域,继承都是用的public 共有继承,当时也没想那么多,觉得共有继承多方便,多简单,反正没有太多的限制,不管是类的成员或者是基类的成员函数都可以访问.没有深究.其实这里面真是 ...
- PHP定义字符串的四种方式
1.简介 在PHP中这门语言中,因为是弱类型语言,因此使用变量时不需提前定义即可使用. 我们在使用php进行开发的时候,大多数使用双引号.单引号进行定义字符串.既然有这两种方式,那么他们之间肯定是有区 ...
- Spring Boot 使用maven打包成jar
1.application.properties加入如下配置 server.port= 2.修改pom.xml <?xml version="1.0" encoding=&q ...
- 深入理解Python字符编码--转
http://blog.51cto.com/9478652/2057896 不论你是有着多年经验的 Python 老司机还是刚入门 Python 不久,你一定遇到过UnicodeEncodeError ...