BZOJ 1982 [Spoj 2021]Moving Pebbles(博弈论)

【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=1982

【题目大意】

  两个人玩游戏. 每次任选一堆,首先拿掉至少一个石头,
  然后移动任意个石子到任意堆中. 谁不能移动了,谁就输了

【题解】

  首先如果对于奇数堆,那么先手必胜,因为可以构建必败态
  对于偶数的情况,如果是石子堆两两相同的对称局面,则为必败态,反之必胜

【代码】

#include <cstdio>
#include <algorithm>
#include <string>
using namespace std;
string s[100010];
char tmp[10010];
int n;
int main(){
    scanf("%d",&n);
    if(n&1){puts("first player");return 0;}
    for(int i=1;i<=n;i++){scanf("%s",tmp);s[i]=tmp;}
    sort(s+1,s+n+1);
    for(int i=1;i<=n;i+=2)if(s[i]!=s[i+1]){puts("first player");return 0;}
    puts("second player");
    return 0;
}
时间: 2024-11-06 21:25:45

BZOJ 1982 [Spoj 2021]Moving Pebbles(博弈论)的相关文章

BZOJ 1982: [Spoj 2021]Moving Pebbles [博弈论 对称]

给你N堆Stone,两个人玩游戏. 每次任选一堆,首先拿掉至少一个石头,然后移动任意个石子到任意堆中. 谁不能移动了,谁就输了... 以前在poj做过已经忘记了... 构造对称,选最多的一堆往其他堆分构造对称局面,先手必胜 一开始就对称,先手必败 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using

BZOJ 1982 Spoj 2021 Moving Pebbles 博弈论

题目大意:给定n堆石子,每次可以选择一堆石子,拿走任意个,然后将堆中剩余石子移动任意个到任意一些堆里,不能操作者为输,求是否先手必胜 必败状态为:n为偶数,且将石子数相同的堆两两配对可以配成n2对 例如: 6 1 1 4 4 5 5 这就是一个先手必败的初始状态 证明: 首先证明这个状态是必败的 由于堆可以两两配对,因此无论先手做什么,后手都可以对另一个堆做同样的事情,故先手必败 对于一种其他状态,先手可以用一步将状态变为必败状态,故其他状态下先手必胜 如果初始有奇数堆石子,那么先手可以将最小的

bzoj1982 [Spoj 2021]Moving Pebbles 博弈论

开始还以为要用sg函数. 想了半天想不出来. 后来才发现想错了. /**************/ 显而易见,当n为偶数并且a[i]可以两两配对时,状态为先手必败. 因为无论你做什么操作对方都可以做另外一个操作来抵消你的操作. 其他情况是先手必胜.你总能通过一步变为先手必败的状态. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace

[BZOJ1982][POJ1740][Spoj 2021]Moving Pebbles|解题报告

这道题的题意BZ和POJ上的都不大清楚... 大概就是给出n堆石子,以及初始每堆石子的个数 两个玩家交替操作,每个操作可以任意在一堆中取任意多的石子 然后再从这堆里拿若干个石子放到某个当前还存在的堆里,当然这个操作也可以不做 问先手还是后手有必胜策略 博弈的题目果然是脑洞大啊... 最后的结论: 对于奇数堆,先手必胜 偶数堆时,先手败当且仅当所有的堆都可以分成两两相等的堆 证明大概就是: 首先考虑1堆的情况,先手显然胜 考虑两堆且相等的情况,如果先手拿完,后手把剩下一堆拿完:如果先手没拿完 后手

[SPOJ2021] Moving Pebbles

[SPOJ2021] Moving Pebbles 题目大意:给你\(N\)堆\(Stone\),两个人玩游戏. 每次任选一堆,首先拿掉至少一个石头,然后移动任意个石子到任意堆中. 谁不能移动了,谁就输了 Solution n为偶数,这些石子堆都是可以两两配对的石子堆,后手必胜,那么无论如何先手对它移动,后手都可以对另一个配对的石子堆做相应的调整. n为偶数,但是石子不可以两两配对,先手必胜,可以令最高堆与最低堆相同,然后将其他堆的石子数补成两两相同. \(n\)为奇数,先手必胜,因为先手一定可

BZOJ 1002 + SPOJ 104 基尔霍夫矩阵 + 一个递推式。

BZOJ 1002 高精度 + 递推 f[1] = 1; f[2] = 5; f[i] = f[i - 1] * 3 - f[i - 2] + 2; SPOJ 104 裸 + 不用Mod 1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <algorithm> 5 #include <iostream> 6 7 using namespace std;

bzoj 2820 / SPOJ PGCD 莫比乌斯反演

那啥bzoj2818也是一样的,突然想起来好像拿来当周赛的练习题过,用欧拉函数写掉的. 求$(i,j)=prime$对数 \begin{eqnarray*}\sum_{i=1}^{n}\sum_{j=1}^{m}[(i,j)=p]&=&\sum_{p=2}^{min(n,m)}\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{p}\rfloor}[i⊥j]\newline&=&\sum_{p=

BZOJ 2588: Spoj 10628. Count on a tree 主席树+lca

2588: Spoj 10628. Count on a tree Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文. Input 第一行两个整数N,M. 第二行有N个整数,其中第i个整数表示点i的权值. 后面N-1行每行两个整数(x,y),表示点x到点y有一条边. 最后M行每行两个整数(u,v,k),表示一组询问.

BZOJ 2226: [Spoj 5971] LCMSum( 数论 )

∑lcm(i,n) = ∑ i*n/(i,n) = ∑d|n∑(x,n)=d x*n/d = ∑d|n∑(t,n/d)=1t*n = n∑d|nf(d). f(d)表示1~d中与d互质的数的和, 即f(d) = d*φ(d)/2(d>=2). 然后O(n)筛φ, 每次询问暴力算即可...最大是100w,sqrt(100w)=1000内的质数是168个, 所以复杂度是O(n + T*168), 可以AC  ----------------------------------------------