BZOJ 1982 Spoj 2021 Moving Pebbles 博弈论

题目大意:给定n堆石子,每次可以选择一堆石子,拿走任意个,然后将堆中剩余石子移动任意个到任意一些堆里,不能操作者为输,求是否先手必胜

必败状态为:n为偶数,且将石子数相同的堆两两配对可以配成n2对

例如:

6

1 1 4 4 5 5

这就是一个先手必败的初始状态

证明:

首先证明这个状态是必败的

由于堆可以两两配对,因此无论先手做什么,后手都可以对另一个堆做同样的事情,故先手必败

对于一种其他状态,先手可以用一步将状态变为必败状态,故其他状态下先手必胜

如果初始有奇数堆石子,那么先手可以将最小的堆和第二小的堆配对,第三小的堆和第四小的堆配对,…,然后用最大的堆填补差值,显然一定能填补上;

如果初始有偶数堆石子,那么先手可以将最大的堆和最小的堆配对,第二小的堆和第三小的堆配对,第四小的堆和第五小的堆配对,..,用最大的堆多出来的部分填补差值,显然也一定能填补上

故其他状态先手必胜

#include <string>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
using namespace std;
int n;
char s[M];
string a[M];
int main()
{
    int i;
    cin>>n;
    if(n&1)
        return cout<<"first player"<<endl,0;
    for(i=1;i<=n;i++)
    {
        scanf("%s",s+1);
        a[i]=s+1;
    }
    sort(a+1,a+n+1);
    for(i=1;i<=n;i+=2)
        if(a[i]!=a[i+1])
            return cout<<"first player"<<endl,0;
    return cout<<"second player"<<endl,0;
}
时间: 2024-10-07 00:22:03

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(博弈论)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1982 [题目大意] 两个人玩游戏. 每次任选一堆,首先拿掉至少一个石头, 然后移动任意个石子到任意堆中. 谁不能移动了,谁就输了 [题解] 首先如果对于奇数堆,那么先手必胜,因为可以构建必败态 对于偶数的情况,如果是石子堆两两相同的对称局面,则为必败态,反之必胜 [代码] #include <cstdio> #include <algorithm> #include &

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  ----------------------------------------------