Slime and Stones

Slime and Stones
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)

Problem Description

Orac and Slime are playing a game.

There are two groups of stones, the first group contains a stones and the second contains b stones. Orac and Slime operate them by turns in the game. For each operation, they have two choices:

  1. Pick up any number of stones from a certain group;

  2. Pick up x x x stones from the first group and y y y from the second group, which x , y x,y x,y satisfy ∣ x − y ∣ ≤ k |x−y|≤k xyk. k is a given constant.

Notice that not picking up any stone in an operation is not allowed. If there is no stone left in both groups at the beginning of one’s turn, he loses the game.

Orac would like to know whether there exists a winning strategy for him if he operates first. They will play many times, so he will make multiple queries.

Input

The first line contains one integer T ( 1 ≤ T ≤ 1 0 5 ) T(1≤T≤10^5) T(1T105), which stands for the number of queries that Orac makes.
In the following T T T lines, each line contains three integer a , b , k ( 1 ≤ a ≤ 1 0 8 , 1 ≤ b ≤ 1 0 8 , 0 ≤ k ≤ 1 0 8 ) . a,b,k(1≤a≤10^8,1≤b≤10^8,0≤k≤10^8). a,b,k(1a108,1b108,0k108).

Output

The output contains T T T lines, with an integer 0 0 0 or 1 1 1 in each line, stand for there exist/not exist a winning strategy for the given situation.

Sample Input

4
1 2 0
2 4 0
1 2 1
2 6 1

Sample Output

0
1
1
0

Hint

In the first query, if Orac picks up all the stones from a group, Slime will pick up all the stones from the other group, and if Orac picks up a stone from the second group, Slime will pick up a stone from both groups.

思路

易知 k = 0 k=0 k=0 时为威佐夫博弈的一般形式。
k = 1 k=1 k=1 时,我们可以利用威佐夫博弈的类似推导方——去寻找必败态。
对于两个石堆 ( a , b ) (a,b) (a,b),不妨设 a ≤ b a≤b ab,稍加打表可以得到
( 1 , 3 ) ( 2 , 6 ) ( 4 , 10 ) ( 5 , 13 ) ( 7 , 17 ) ( 8 , 20 ) (1,3)\\ (2,6)\\ (4,10)\\ (5,13)\\ (7,17)\\ (8,20) (1,3)(2,6)(4,10)(5,13)(7,17)(8,20)

于是我们可以得到一个规律:
a [ i ] = a [ i ] a[i]=a[i] a[i]=a[i] b [ i ] b[i] b[i]中未出现的最小值,
b [ i ] = a [ i ] + 2 ∗ i b[i]=a[i]+2*i b[i]=a[i]+2i
我们知道威佐夫博弈的通项是 a [ i ] = [ i ∗ f ] ( 下 取 整 ) , b [ i ] = a [ i ] + i , ( f = 1 + 5 2 ) a[i]=[i∗f](下取整),b[i]=a[i]+i,(f=\frac{1+\sqrt{5}}{2}) a[i]=[if](),b[i]=a[i]+i,(f=21+5 )
这个和威佐夫博弈的形式很像,所以我们可以用类似的方法推导公式——Betty方程(具体证明过程请自行百度贝蒂定理,这里不再赘述)。
我们列出Betty方程
1 α + 1 α + k + 1 = 1 \frac{1}{α}+\frac{1}{α+k+1}=1 α1+α+k+11=1
解得
α = 1 − k + k 2 + 2 k + 5 2 α=\frac{1-k+\sqrt{k^2+2k+5}}{2} α=21k+k2+2k+5
因此我们可以得到
a [ i ] = ⌊ 1 − k + k 2 + 2 k + 5 2 i ⌋ a[i]=⌊\frac{1-k+\sqrt{k^2+2k+5}}{2}i⌋ a[i]=21k+k2+2k+5 i
b [ i ] = ⌊ 3 + k + k 2 + 2 k + 5 2 i ⌋ b[i]=⌊\frac{3+k+\sqrt{k^2+2k+5}}{2}i⌋ b[i]=23+k+k2+2k+5 i
所以验证的时候只需要先计算i即可。
注意到
b [ i ] − a [ i ] = ( k + 1 ) i b[i]−a[i]=(k+1)i b[i]a[i]=(k+1)i
所以 i = b [ i ] − a [ i ] k + 1 ( ( b [ i ] − a [ i ] ) 必 须 整 除 ( k + 1 ) ) i=\frac{b[i]−a[i]}{k+1}((b[i]-a[i])必须整除(k+1)) i=k+1b[i]a[i]((b[i]a[i])(k+1))
然后验证下 a [ i ] , b [ i ] a[i],b[i] a[i],b[i]的值对不对即可(按理来说只需要验证一个,但 α α α 是个浮点数,会有精度误差)

#pragma GCC optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;
#define ls (rt<<1)
#define rs (rt<<1|1)
typedef long long ll;
template <typename T>
inline void read(T &x) {
    x = 0;
    static int p;
    p = 1;
    static char c;
    c = getchar();
    while (!isdigit(c)) {
        if (c == '-')p = -1;
        c = getchar();
    }
    while (isdigit(c)) {
        x = (x << 1) + (x << 3) + (c - 48);
        c = getchar();
    }
    x *= p;
}
template <typename T>
inline void print(T x) {
    if (x<0) {
        x = -x;
        putchar('-');
    }
    static int cnt;
    static int a[50];
    cnt = 0;
    do {
        a[++cnt] = x % 10;
        x /= 10;
    } while (x);
    for (int i = cnt; i >= 1; i--)putchar(a[i] + '0');
    puts("");
}
const double pi=acos(-1);
const double eps=1e-6;
const int mod = 1e9+9;
const int inf = 0x3f3f3f3f;
const int maxn = 4e5+10;

ll a,b,k,c;
inline void work() {
    read(a);
    read(b);
    read(k);
    if (a > b) swap(a, b);
    if ((b - a) % (k + 1)) {
        puts("1");
        return;
    }
    double r = (sqrt(k * k + 2 * k + 5.0) - k + 1) / 2.0;
    if (a == (ll) (r * (b - a) / (k + 1)))
        puts("0");
    else
        puts("1");
}
int main() {
    //freopen("1.txt","r",stdin);
    int T = 1;
    read(T);
    while (T--) {
        work();
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值