【XSY2988】取石子

题目来源:NOI2018模拟测试赛(二十六)

题解:

设a<b;

可以先考虑a=1的特殊情况,注意到后手的最优策略是跟着另外一个人取,取到最后剩余不到$a+b$时再看奇偶性;

那么很容易想到把所有石子按$\mod(a+b)$的余数分类:

1.余数<a:剩下的部分没用;

2.a≤余数<b:只要有则a必胜;

3.b≤余数<2a:要考虑奇偶性;

4.余数≥2a:只要有两个或以上则a必胜,有一个时情况3的为偶数则先手必胜,为奇数则a必胜,没有时情况3为偶数则后手必胜,否则先手必胜;

随便手推一下就行了。

ps:场上会a=b和a=1的都写了正解,就我一个zz不会还写挂了部分分……

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<queue>
 7 #define inf 2147483647
 8 #define eps 1e-9
 9 #define mod 1000000007
10 using namespace std;
11 typedef long long ll;
12 typedef double db;
13 int n,a,b,s1,s2,s3,s4,t1,t2,t3,t4,tot=0,x[100001],s[100001];
14 bool sw=false;
15 int fastpow(int x,int y){
16     int ret=1;
17     for(;y;y>>=1,x=(ll)x*x%mod){
18         if(y&1)ret=(ll)ret*x%mod;
19     }
20     return ret;
21 }
22 int main(){
23     scanf("%d%d%d",&n,&a,&b);
24     if(a>b){
25         sw=true;
26         swap(a,b);
27     }
28     for(int i=1;i<=n;i++){
29         scanf("%d",&x[i]);
30         x[i]%=(a+b);
31         if(x[i]<a)s1++;
32         else if(x[i]<b)s2++;
33         else if(x[i]<a*2)s3++;
34         else s4++;
35     }
36     if(s3){
37         t3=t4=fastpow(2,s1+s3-1);
38     }else t4=fastpow(2,s1);
39     t3=(t3+(ll)t4*s4%mod)%mod;
40     t1=((fastpow(2,n)-t3-t4)%mod+mod)%mod;
41     if(sw)swap(t1,t2);
42     printf("%d %d %d %d",t1,t2,t3,t4);
43     return 0;
44 }

猜你喜欢

转载自www.cnblogs.com/dcdcbigbig/p/10062865.html