题意:
两堆石子,给一个
k
k
k。
你可以对一堆石子取任意个,也可以对两堆石子取x,y个,保证|x-y|≤k。
先取完获胜,求先手能否获胜。
思路:
建议去看大佬博客
以为是思维题,想了很久,结果是算法题orz。
对于威佐夫博弈,就是题中
k
=
0
k=0
k=0的情况
1
a
+
1
a
+
1
=
1
\frac{1}{a}+\frac{1}{a+1}=1
a1+a+11=1
由此求出 a = 1 + 5 2 a=\frac{1+\sqrt{5}}{2} a=21+5
那么必败态就是
A
=
a
∗
n
,
B
=
A
+
n
A=a*n,B=A+n
A=a∗n,B=A+n,
n
n
n代表是第几项必败态。(具体证明感觉很复杂,可以参考链接)
那么只要先手属于必败态,那么必输,否则就必胜。
本题中多了个
k
k
k,实际就是变成了
1
a
+
1
a
+
1
+
k
=
1
\frac{1}{a}+\frac{1}{a+1+k}=1
a1+a+1+k1=1
令
k
=
k
+
1
k=k+1
k=k+1
变形成
a
2
+
(
k
−
2
)
∗
a
−
k
=
0
a^2+(k-2)*a-k=0
a2+(k−2)∗a−k=0
同样可得必败态为 A = a ∗ n , B = A + n ∗ k A=a*n,B=A+n*k A=a∗n,B=A+n∗k
我们已知
A
,
B
A,B
A,B,只需要二分判断是否存在相应的
n
n
n,使得式子成立即可。
式子成立,说明先手必败,否则必胜。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 7;
ll a,b,k;
ll get() { //寻找是第几项必败态
ll A = 1,B = k - 2,C = -k;
ll res = B * B - 4 * A * C;
ll l = 0,r = 1e8 + 7;
while(l <= r) {
ll mid = (l + r) / 2;
ll now = mid * ((-B + sqrt(res)) / 2);
if(now > a) {
r = mid - 1;
} else if(now < a) {
l = mid + 1;
} else {
return mid;
}
}
return -1;
}
int main() {
int T;scanf("%d",&T);
while(T--) {
scanf("%lld%lld%lld",&a,&b,&k);
if(a > b) swap(a,b);
k++;
ll n = get();
if(n == -1) printf("1\n");
else {
if(b - a == n * k) printf("0\n");
else printf("1\n");
}
}
return 0;
}