zoukankan      html  css  js  c++  java
  • 5507. 【清华冬令营2018模拟】取石子

    题目描述

    有n堆石子,第i堆有xi个。
    Alice和Bob轮流取石子(先后手未定),Alice每次从一堆中取走a个,Bob每次从一堆中取走b个,无法操作者输。
    不难发现只会有四种情况:Alice必胜;Bob必胜;先手必胜;后手必胜。
    你需要选定若干堆石子(共有2^n种方案),Alice和Bob只能在你选出的堆中取,问以上四种情况对应的方案数。

    1<=n<=100000,1<=a,b,xi<=10^9

    题解

    首先一堆个数为s的石子等价于s%(a+b)的石子,可以从0~a+b-1归纳到k(a+b)~(k+1)(a+b)-1

    感觉大概是一个人如果选了而另一个人没选,则局面就会改变,由于双方都是绝顶聪明,所以第一个人肯定是朝着利于自己的方向操作,而另一个人必然会阻止他

    设a<=b,把石子分成四类:x>=a&x<b,a<=x<2a&x>=b,x>=2a&x>=b,x<a&x<b

    第四类对于情况没有影响,在最后的方案乘2^s4

    由于x<a+b,所以一个人选了之后另一个人不能再选,且b只能取一次,a可能可以取多次

    分类讨论

    ①选了第一类 或 不选第一类且第三类选了>=2:因为第一类只能由A选,所以A无论先后手都可以留出一步来取胜;第三类选了至少两个的话B就拆不掉,所以A也必胜

    ②不选一三类:第二类对于AB都一样,所以奇数先手胜偶数后手胜

    ③不选第一类且第三类选了一个:A先手必胜,A后手B先手时B一定会先拆掉第三类,所以第二类奇数A胜偶数B胜,因此第二类选奇数A必胜偶数先手必胜

    code

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define mod 1000000007
    #define ll long long
    #define file
    using namespace std;
    
    int a[100001],n,A,B,i,j,k,l,s1,s2,s3,s4;
    ll ans,ans1,ans2,ans3,ans4;
    bool bz;
    
    ll qpower(ll a,int b) {ll ans=1; while (b) {if (b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;} return ans;}
    void swap(int &x,int &y) {int z=x;x=y;y=z;}
    
    int main()
    {
    	freopen("stone.in","r",stdin);
    	#ifdef file
    	freopen("stone.out","w",stdout);
    	#endif
    	
    	scanf("%d%d%d",&n,&A,&B);
    	if (A>B) swap(A,B),bz=1;
    	fo(i,1,n)
    	{
    		scanf("%d",&a[i]),a[i]%=(A+B);
    		if (a[i]<A) ++s4;
    		else
    		{
    			if (a[i]<A*2)
    			{
    				if (a[i]<B) ++s1;
    				else ++s2;
    			}
    			else
    			{
    				if (a[i]<B) ++s1;
    				else ++s3;
    			}
    		}
    	}
    	
    	ans1=(qpower(2,s1)-1)*(qpower(2,s2+s3))%mod+(qpower(2,s3)-1-s3)*qpower(2,s2)%mod;
    	ans2=0;
    	if (s2)
    	ans1+=qpower(2,s2-1)*s3,ans3=qpower(2,s2-1)*(1+s3),ans4=qpower(2,s2-1);
    	else
    	ans3=s3,ans4=1;
    	
    	if (bz) swap(ans1,ans2);
    	ans1=(ans1+mod)%mod*qpower(2,s4)%mod;
    	ans2=(ans2+mod)%mod*qpower(2,s4)%mod;
    	ans3=(ans3+mod)%mod*qpower(2,s4)%mod;
    	ans4=(ans4+mod)%mod*qpower(2,s4)%mod;
    	printf("%lld %lld %lld %lld
    ",ans1,ans2,ans3,ans4);
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    Android API Guides---Storage Access Framework
    Memcache安装与使用
    Can a GridView have a footer and header just like ListView?
    【大话设计模式】——简单工厂模式
    三层架构—简析
    OpenStack 使用Ceph 配置指导
    mysql 8小时问题
    centos7 安装mysql
    mysql 创建用户
    Waiting for table metadata lock
  • 原文地址:https://www.cnblogs.com/gmh77/p/13657121.html
Copyright © 2011-2022 走看看