【AGC002E】Candy Piles 博弈论

题目大意

  有 n 堆糖果,第 i 堆有 ai 个。

  两个人轮流决策,决策分为两种:

   1.选择糖果数最多的一堆糖果,并把这堆糖全吃了。

   2.在每堆非空的糖果堆里拿一颗糖吃掉。

  吃掉最后一颗糖的人输。问你先手必胜还是先手必败。

   n100000

题解

  又是一个打表结论题。

  先把 ai 从大到小排序。

  设 fi,j 为删掉前 i 大,每堆删掉 j 个后是先手必胜还是先手必败。先把所有的 fi,j 算出来。

  如果都删完了,就先手必胜。

  打个表可以发现,一条斜线上的结果相同。

  这个结论还是挺好证的。这里就不证了。

  【AGC002E】Candy Piles 博弈论_第1张图片

  直接找到 (0,0) 对应的是哪个点 (i,i) ,算出这个点到上方和右方轮廓的距离,只要有一个是偶数,就先手必胜。

  时间复杂度: O(n)

代码

#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
int a[100010];
int main()
{
#ifdef DEBUG
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
#endif
    int n;
    int i;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
    sort(a+1,a+n+1,greater<int>());
    int ans;
    a[0]=a[1];
    for(i=0;i<=n;i++)
        if(a[i+1]<=i)
        {
            ans=(a[i]-i)&1;
            int j=i+1;
            while(j<=n&&a[j]==i)
                j++;
            if((j-i+1)&1)
                ans=1;
            break;
        }
    if(ans)
        printf("First\n");
    else
        printf("Second\n");
    return 0;
}

你可能感兴趣的:(博弈论)