威佐夫博弈及其拓展

威佐夫博弈

普通威佐夫博弈:

两种操作:一、同时在两堆上取相同的个数。二、在某一堆上取任意个数。(每次取不为0)

a [ n ] = n α , b [ n ] = a [ n ] + n , α = 1 + 5 2 a[n] = n \alpha, b[n] = a[n] + n,\alpha = \frac{1 + \sqrt5}{2} a[n]=nα,b[n]=a[n]+n,α=21+5 ,这个时候是可以确定必败状态的。

这里就不详细展开证明了。

威佐夫博弈拓展:

两种操作:一、同时在两堆分别取 x , y , ∣ x − y ∣ < = k x, y, \mid x - y \mid <= k x,yxy<=k。二、在某一堆上取任意个数。(每次取不为0)

对于给定的限定 k k k,于是题目判定变成了 a [ n ] = n α , b [ n ] = a [ n ] + ( k + 1 ) n a[n] = n \alpha, b[n] = a[n] + (k + 1)n a[n]=nα,b[n]=a[n]+(k+1)n,带入 k k k等于0的时候也就是普通情况下成立,

所以我们可以先解得 α \alpha α,然后再通过二分去寻找是否有符合要求的 n n n,这个时候 α \alpha α的有关方程是 1 α + 1 α + k + 1 = 1 \frac{1}{\alpha} + \frac{1}{\alpha + k + 1} = 1 α1+α+k+11=1

即可解的方程然后带入验证即可。

取(2堆)石子游戏(普通威佐夫)

/*
  Author : lifehappy
*/
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>

#define mp make_pair
#define pb push_back
#define endl '\n'
#define mid (l + r >> 1)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define ls rt << 1
#define rs rt << 1 | 1

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const double pi = acos(-1.0);
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;

inline ll read() {
    ll f = 1, x = 0;
    char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-')    f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    return f * x;
}

int main() {
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int a, b;
    while(cin >> a >> b && (a + b)) {
        map<int, int> MP;
        if(a < b) swap(a, b);
        int k = (a - b) * ((1 + sqrt(5)) / 2);
        if(k == b) {
            puts("0");
            continue;
        }
        puts("1");
        for(int i = 1; i <= b; i++) {
            int n = a - i, m = b - i;
            int k = (n - m) * ((1 + sqrt(5)) / 2);
            if(k == m) {
                printf("%d %d\n", m, n);
            }
        }
        for(int i = 1; i <= a; i++) {
            int n = a - i, m = b;
            if(n < m) swap(n, m);
            int k = (n - m) * ((1 + sqrt(5)) / 2);
            if(MP[m] == n) continue;
            MP[m] = n;
            if(k == m) {
                printf("%d %d\n", min(n, m), max(n, m));
            }
        }
        for(int i = 1; i <= b; i++) {
            int n = a, m = b - i;
            if(n < m) swap(n, m);
            int k = (n - m) * ((1 + sqrt(5)) / 2);
            if(MP[m] == n) continue;
            MP[m] = n;
            if(k == m) {
                printf("%d %d\n", m, n);
            }
        }
    }
    return 0;
}

Slime and Stones(拓展威佐夫)

/*
  Author : lifehappy
*/
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>

#define mp make_pair
#define pb push_back
#define endl '\n'
#define mid (l + r >> 1)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define ls rt << 1
#define rs rt << 1 | 1

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const double pi = acos(-1.0);
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;

inline ll read() {
    ll f = 1, x = 0;
    char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-')    f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    return f * x;
}

ll calc(ll n, ll k) {
    double A = 1, B = k - 2, C = -k;
    double a = (sqrt(B * B - 4 * A * C) - B) / (2 * A);
    ll l = 1, r = 1e9;
    while(l < r) {
        ll Mid = l + r >> 1;
        ll now = Mid * a + k * Mid;
        if(now >= n) r = mid;
        else l = mid + 1;
    }
    ll now = l * a + k * l;
    return now == n ? l : -1;
}

int main() {
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int T = read();
    while(T--) {
        ll a = read(), b = read(), k = read() + 1;
        if(a < b) swap(a, b);
        ll n = calc(a, k);
        if(n == -1) puts("1");
        else {
            if(a - b == n * k) puts("0");
            else puts("1");
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值