zoukankan      html  css  js  c++  java
  • 【AGC002E】Candy Piles 博弈论

    题目大意

      有(n)堆糖果,第(i)堆有(a_i)个。

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

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

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

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

      (nleq 100000)

    题解

      又是一个打表结论题。

      先把(a_i)从大到小排序。

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

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

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

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

      

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

      时间复杂度:(O(n))

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    #include<utility>
    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
    ");
    	else
    		printf("Second
    ");
    	return 0;
    }
    
  • 相关阅读:
    [模板]KMP
    [BZOJ] 1833: [ZJOI2010]count 数字计数
    [BZOJ] 1563: [NOI2009]诗人小G
    [BZOJ] 2442: [Usaco2011 Open]修剪草坪
    [LOJ] #2360. 「NOIP2016」换教室
    9.18模拟赛
    [BZOJ] 2006: [NOI2010]超级钢琴
    [BZOJ] 1143: [CTSC2008]祭祀river
    [51Nod] 1218 最长递增子序列 V2
    [BZOJ] 3307: 雨天的尾巴
  • 原文地址:https://www.cnblogs.com/ywwyww/p/8513316.html
Copyright © 2011-2022 走看看