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;
    }
    
  • 相关阅读:
    ny 58 最少步数 (BFS)
    Oracle 参数文件
    Oracle 密码文件
    Oracle 表空间与数据文件
    Oracle 回滚(ROLLBACK)和撤销(UNDO)
    Oracle 控制文件(CONTROLFILE)
    Oracle 联机重做日志文件(ONLINE LOG FILE)
    Oracle 常用目录结构(10g)
    Oracle 归档日志
    instance_name,db_name,oracle_sid之间的关系
  • 原文地址:https://www.cnblogs.com/ywwyww/p/8513316.html
Copyright © 2011-2022 走看看