牛客練習賽59 石子搬運

https://ac.nowcoder.com/acm/contest/4743/E

就是說每次能取走一半
我是這樣想的 如果先手取掉一半後的贏的是後手,那麼先手就一定贏
因爲我取掉一半之後 先手後手位置轉變了 先手取了這一部分 剩下那部分的贏家是原來的後手 此時先手變成了後手 自然是最開始的先手贏

然後寫了幾個找下規律
0 1 3 6 13 26 53 106
0-1是Q贏
2到3是H贏
4到6是Q贏
7到13是H贏
14到26是Q贏
27到53是H贏
54到106是Q贏
注意一下因爲H先手所以他如果可以把Q變成必敗方一定優先的
舉個例子 比如就說27 分成兩部分是13 14
因爲H先手 那麼27-13=14 27-14=13
如果H拿走13 剩餘14 我們發現n=14時候是Q贏也就是後手贏
取走後 H和Q先後手關係轉變 H從先手變成了後手 那麼H就必贏
那麼對於53 兩部分是26 27
因爲n=26是Q贏 也就是後手贏 那麼H就取走27那一部分 H就變成了後手
所以n=53時候 H贏

計算間隔的差是 1 2 3 7 13 27 53
找下規律 發現對於偶數位置就是前一項的兩倍加1
奇數位置就是前一項的兩倍減1

然後寫一下就好了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define me(a,x) memset(a,x,sizeof a)
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define all(x) (x).begin(), (x).end()
#define pb(a) push_back(a)
#define paii pair<int,int>
#define pali pair<ll,int>
#define pail pair<int,ll>
#define pall pair<ll,ll>
#define fi first
#define se second
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
      ll n,m;cin>>n;
      if(n==1){puts("XiaoQiao");continue;}
      ll sum=1,k=2;
      int ans=0;
       for(;sum<n;ans++){
        if(ans&1) sum=sum+k,k=2*k+1;
        else sum=sum+k,k=2*k-1;
        //printf("%lld %lld\n",sum,k);
     }
     puts((!(ans&1))?"XiaoQiao":"XiaoHuiHui");
  
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章