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:
The first line contains one integer T ( 1 ≤ T ≤ 1 0 5 ) T(1≤T≤10^5) T(1≤T≤105), 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(1≤a≤108,1≤b≤108,0≤k≤108).
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.
4
1 2 0
2 4 0
1 2 1
2 6 1
0
1
1
0
n 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\leq b a≤b,稍加打表可以得到
(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 + 1 ) b[i]=a[i]+2*(i+1) b[i]=a[i]+2∗(i+1)
我们知道威佐夫博弈的通项是 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]=[i∗f],b[i]=a[i]+i,(f=21+5)
这个和威佐夫博弈的形式很像,所以我们可以用类似的方法推导公式——Betty方程(具体证明过程请自行百度贝蒂定理,这里不再赘述)。
我们列出Betty方程 1 α + 1 α + k + 1 = 1 \frac{1}{\alpha}+\frac{1}{\alpha+k+1}=1 α1+α+k+11=1
解得 α = 1 − k + k 2 + 2 k + 5 2 \alpha=\frac{1-k+\sqrt{k^2+2k+5}}{2} α=21−k+k2+2k+5
因此我们可以得到
a [ i ] = ⌊ 1 − k + k 2 + 2 k + 5 2 i ⌋ a[i]=\lfloor\frac{1-k+\sqrt{k^2+2k+5}}{2}i\rfloor a[i]=⌊21−k+k2+2k+5i⌋
b [ i ] = ⌊ 3 + k + k 2 + 2 k + 5 2 i ⌋ b[i]=\lfloor\frac{3+k+\sqrt{k^2+2k+5}}{2}i\rfloor b[i]=⌊23+k+k2+2k+5i⌋
所以验证的时候只需要先计算 i i i即可。
注意到 b [ i ] − a [ i ] = ⌊ ( k + 1 ) i ⌋ b[i]-a[i]=\lfloor (k+1)i\rfloor b[i]−a[i]=⌊(k+1)i⌋
所以 i = ⌊ b [ i ] − a [ i ] k + 1 ⌋ i=\lfloor\frac{b[i]-a[i]}{k+1}\rfloor i=⌊k+1b[i]−a[i]⌋
然后验证下 a [ i ] , b [ i ] a[i],b[i] a[i],b[i]的值对不对即可(按理来说只需要验证一个,但 α \alpha α是个浮点数,会有精度误差)
#include
using namespace std;
const int maxn=5e7;
#define _rep(i, a, b) for(int i=(a);i<=(b);i++)
#define _repp(i, a, b) for(int i=(a);i<(b);i++)
#define _per(i, a, b) for(int i=(b);i>=(a);i--)
#define _pper(i, a, b) for(int i=(b);i>(a);i--)
#define mem(a) memset(a,0,sizeof(a))
double f1(double k)
{
double delta=(sqrt(k*k+2*k+5.0)+1-k*1.0)/2.0;
return delta;
}
double f2(double k)
{
double delta=(sqrt(k*k+2*k+5.0)+3+k*1.0)/2.0;
return delta;
}
inline void solve()
{
int t;
scanf("%d", &t);
while(t--)
{
int a,b,k;
scanf("%d%d%d",&a,&b,&k);
if(a>b)
swap(a,b);
double k1=f1(k*1.0);
double k2=f2(k*1.0);
int d=(b-a)/(k+1);
if(floor(d*k1)==a && floor(d*k2)==b)
{
printf("0\n");
}
else
{
printf("1\n");
}
}
}
signed main()
{
// ios_base::sync_with_stdio(false);
// cin.tie(0);
// cout.tie(0);
#ifdef ACM_LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
long long test_index_for_debug=1;
char acm_local_for_debug;
while(cin>>acm_local_for_debug)
{
cin.putback(acm_local_for_debug);
if (test_index_for_debug>100)
{
throw runtime_error("Check the stdin!!!");
}
auto start_clock_for_debug=clock();
solve();
auto end_clock_for_debug=clock();
cout<<"\nTest "<<test_index_for_debug<<" successful"<<endl;
cerr<<"Test "<<test_index_for_debug++<<" Run Time: "
<<double(end_clock_for_debug-start_clock_for_debug)/CLOCKS_PER_SEC<<"s"<<endl;
cout<<"--------------------------------------------------"<<endl;
}
#else
solve();
#endif
return 0;
}
赛时结束前5分钟推出结论,赛后5分钟迟迟AC…
DrGilbert 2020.8.18