gmoj 6823. [2020.10.17 Improve Group Simulation] Candy Game "Game Theory"

topic

https://gmoj.net/senior/#main/show/6823

answer

This is the introductory question of my SG function ...
Let's consider the situation in each pile of stones first, let fi f_ifiIndicates if there are i stones in the pile before the operation, whether the player currently operating is the one who has taken the pile of stones (recorded as 0/1, 0 is not 1), or he can freely choose 0 or 1 state (recorded as 2).
So obviously fb = 0 f_b=0fb=0
f i = m e x { f i ⋅ k , i ≤ ⌊ b k ⌋ f i + 1 , 1 ≤ i < b f_i=mex\begin{cases} f_{i\cdot k}&,i\leq \left\lfloor\frac{b}{k}\right\rfloor\\ f_{i+1} \end{cases},1\leq i<b fi=mex{ fikfi+1,ikb,1i<b
通过打表找规律,可以发现 [ ⌊ b k ⌋ + 1 , b ] , [ ⌊ ⌊ b k ⌋ k ⌋ + 1 , ⌊ b k ⌋ ] , ⋯ \left[\left\lfloor\cfrac{b}{k}\right\rfloor+1,b\right],\left[\left\lfloor\cfrac{\left\lfloor\frac{b}{k}\right\rfloor}{k}\right\rfloor+1,\left\lfloor\cfrac{b}{k}\right\rfloor\right],\cdots [kb+1,b],[kkb+1,kb], Except for the first two fs in these intervals, the other fs are all cyclic, and the cyclic section length is 2 (that is, 0 2 0 2 0 2 0 2...).
Therefore, it is good to maintain the first 4 bits of each interval, and the time complexity of calculating a single heap isO (log ⁡ kb) O(\log_kb)O(logkb ) , the sg function value of this block isfa f_afa.
Then if SG (1) ⨁ SG (2) ⨁… ⨁ SG (n) = 0 SG(1)\bigoplus SG(2)\bigoplus\cdots\bigoplus SG(n)=0SG(1)SG(2)S G ( n )=0 , then Bob wins; otherwise Alice wins (SG theorem).
In fact, it can be understood in another way:

Blocks with a sg value of 0 do not change the sequence, blocks with a sg of 1 force the sequence, and blocks with a sg of 2 can freely choose whether to change the sequence. In the end, the player will win.
The operation of two people can be regarded as two parts: the first part is the block with sg of 0/1, and the second part is the block with sg of 2. The result of the former is fixed. The problem now becomes that at the beginning, one person must lose and the other must win. Each time two people can change or not change the winner, ask who will win in the end.
In fact, whoever has more sg of 2 will win; the same amount will not change the victory situation. Because Alice chooses first, her block with sg of 2 will never be less than Bob. Therefore, when the number of blocks with sg of 2 is odd, Alice will win; when it is even, it is equivalent to ignoring the children of blocks with sg of 2. problem.

CODE

#include<cstdio>
using namespace std;
#define ll long long
#define N 65
ll b,k,g[100005],arr[100005];int cnt,s;
struct block{
    
    int num[4];ll front;}f[N];
inline int search(ll x)
{
    
    
	for(int i=s;i;--i)
		if(x<=f[i].front) return i;
}
inline int calc_f1(ll y)
{
    
    
	int s=search(y);
	if(y>f[s].front-4) return f[s].num[f[s].front-y];
	return f[s].num[2+((y&1)^(f[s].front-2&1))];
}
inline int calc(ll x)
{
    
    
	if(x==arr[cnt]) return g[cnt];
	arr[++cnt]=x;
	int f1=x<=b/k?calc_f1(x*k):2,f2;
	f2=arr[cnt-1]!=x+1?calc_f1(x+1):g[cnt-1];
	if(f1&&f2) return g[cnt]=0;
	if(f1!=1&&f2!=1) return g[cnt]=1;
	return g[cnt]=2;
}
int main()
{
    
    
	freopen("candy.in","r",stdin);
	freopen("candy.out","w",stdout);
	ll a,x;int id,t,n,ans;
	scanf("%d",&t);
	for(id=1;id<=t;++id)
	{
    
    
		scanf("%d",&n),ans=0;
		while(n--)
		{
    
    
			scanf("%lld%lld%lld",&a,&b,&k);
			s=1,cnt=0,f[1]=(block){
    
    0,1,0,0,b};
			for(int i=2;i<4;++i) f[1].num[i]=calc(b-i);
			while(f[s].front/k+1>a&&f[s].front-3>a)
			{
    
    
				x=f[s].front/k,f[++s].front=x;
				for(int i=0;i<4;++i) f[s].num[i]=calc(x-i);
			}
//			for(int i=b-1;i>=a;--i) f[++s].front=i,f[s].num[0]=calc(i);
			ans^=calc_f1(a);//printf("%lld\t%lld\t%lld\t%d\n",a,b,k,calc_f1(a));
		}
		puts(ans?"Alice":"Bob");
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/huangzihaoal/article/details/109188370