Who is better?(斐波那契博弈+拓展中國剩餘定理)

題目鏈接:Who is better?

題意:
兩個人玩遊戲,遊戲規則如下:
有一堆個數爲n的石子,遊戲雙方輪流取石子,滿足:

  1. 先手不能在第一次把所有的石子取完;
  2. 之後每次可以取的石子數介於1到對手剛取的石子數的2倍之間(包含1和對手剛取的石子數的2倍)。
  3. 約定取走最後一個石子的人爲贏家,求必敗態。

現在給你 m 行 a 和 b 表示 n ≡ b (mod a)。
讓你求出 n 。之後根據求出的 n 判斷
先手贏輸出 “Lbnb!”
先手輸輸出 “Zgxnb!”
n 不存在輸出 “Tankernb!”

思路:

  1. 題目就是裸的斐波那契博弈,裸得不能再裸了,然後重點就是求 n ,但是求 n 就又是裸的拓展中國剩餘定理······就很無語

斐波那契博弈:斐波那契博弈

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<unordered_map>
#define inf 0x3f3f3f3f
using namespace std;

typedef long long ll;

const int N = 1010;

int n;
ll m[N],a[N];

ll exgcd(ll a, ll b, ll &x, ll &y)
{
    if(b == 0)
    {
        x=1, y = 0;
        return a;
    }
    ll ret = exgcd(b, a % b, y, x);
    y -= (a / b) * x;
    return ret;
}
ll work()
{
    ll M = m[1], A = a[1], t, d, x, y;
    for(int i = 2; i <= n; i++)
    {
        d = exgcd(M, m[i], x, y);
        if((a[i] - A) % d) return -1;
        x *= (a[i] - A) / d, t = m[i] / d, x = (x % t + t) % t;
        A = M * x + A, M = M / d * m[i], A %= M;
    }
    A = (A % M + M) % M;
    return A;
}
int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%lld %lld", &m[i], &a[i]);
    }
    ll ans = work();
    if(ans == -1)
    {
        printf("Tankernb!\n");
    }
    else
    {
        ll pre1 = 0;
        ll pre2 = 1;
        ll sum = 0;
        while(sum < ans)
        {
            sum = pre1 + pre2;
            pre1 = pre2;
            pre2 = sum;
        }
        if(sum == ans)
        {
            printf("Lbnb!\n");
        }
        else
        {
            printf("Zgxnb!\n");
        }
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章