AGAME - Editorial

PROBLEM LINK:

Practice
Contest: Division 1
Contest: Division 2
Contest: Division 3
Contest: Division 4

Author: arnob918
Tester: yash_daga
Editorialist: iceknight1093

DIFFICULTY:

TBD

PREREQUISITES:

None

PROBLEM:

Alice and Bob play a game on N piles of stones.
On Alice’s turn, she chooses two piles whose indices have the same parity, and removes one stone from each.
On Bob’s turn, he chooses two piles whose parities are different and transfers a stone from one to the other.
Under optimal play, who wins if Alice starts first?

EXPLANATION:

Let’s get a trivial edgecase out of the way first: if N = 1, Bob can’t make any moves at all; so Alice wins if A_1 \geq 2 (so she can make a move and pass the turn) and loses otherwise.

Now, let’s look at N \geq 2.
Observe that as long as at least one stone remains, Bob can always make a move.
Further, only Alice can reduce the total number of stones, since Bob’s move only moves things around.
So, Alice can win only if she’s the one to remove the last stone.

In particular, since Alice removes two stones at a time; if the total number of stones is odd Alice can never win.

So, let’s look at the case when N \geq 2, and the total number of stones is even.
Let S_{\text{odd}} = A_1 + A_3 + A_5 + \ldots denote the number of stones at odd-indexed piles,
and S_{\text{even}} = A_2 + A_4 + A_6 + \ldots denote the number of stones at even-indexed piles.

Note that:

  • Alice’s move subtracts 2 from either S_{\text{odd}} or S_{\text{even}}; and
  • Bob’s move subtracts 1 from one and adds 1 to the other.

In particular, after Alice’s move the parity of both quantities doesn’t change, and after Bob’s move the parity of both quantities changes.
Further, since the total number of stones is even, both S_{\text{odd}} and S_{\text{even}} will have the same parity.

Notice that this essentially “uniquely” determines the process of the game, in terms of parities.
For instance, if initially S_{\text{odd}} is even, the game proceeds as follows:

0 \xrightarrow{\text{Alice}} 0 \xrightarrow{\text{Bob}} 1 \xrightarrow{\text{Alice}} 1 \xrightarrow{\text{Bob}} 0 \xrightarrow{\text{Alice}} 0 \xrightarrow{\text{Bob}} 1 \xrightarrow{\text{Alice}} 1 \xrightarrow{\text{Bob}} 0 \to \ldots

where 0 means both quantities are even, and 1 means they’re odd.

Alice needs to make exactly \frac{\sum A_i}{2} moves (let this be X) to ensure she wins.
In particular, since she’ll make the last move, she needs to ensure that the parity is 0 after her last move.

From the pattern above, it can be seen that if the initial state is 0 and X is even, or if the initial state is 1 but X is odd, this is impossible: after X moves, the state will be 1 which can never be Alice’s win.

In the other two cases, Alice will win.

Proof

If the current state is 0, i.e, there’s an even number of stones at both the odd-index and even-index piles, Alice can always make a move: at least one set of piles will have a positive number of stones (since only Alice can remove stones), and since this number is even that set will have \geq 2 stones which Alice can remove two of.

If the current state is 1, there’s exactly one state when Alice will be unable to move: when there’s one stone at an even pile, and one stone at an odd pile.
However, via our parity argument, reaching such a state is impossible if:

  • The starting state is 0, and Alice needs to make an odd number of moves (just before her last move, she would have made an even number of moves; so Bob would’ve done the same and the current state will be )); or
  • The starting state is 1, and Alice needs to make an even number of moves (the same argument tells us that Bob would’ve made an odd number of moves; making the state 0 again).

Notice that those are exactly the states we’re claiming Alice to win!

Checking the required conditions is easy in linear time, since all we do is:

  • Compute the sum of all piles and divide by 2 to find X, the number of moves Alice needs to make.
  • Compute the sum of even-indexed piles to figure out the starting state.

TIME COMPLEXITY:

\mathcal{O}(N) per testcase.

CODE:

Author's code (C++)
#include <bits/stdc++.h>

using namespace std;

#define Q                   int totalcase; cin >> totalcase; for(int caseno=1; caseno<=totalcase; caseno++)
typedef long long               ll;
int a[100005];

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    Q{
        int n;
        cin >> n;
        int sum = 0;
        int od = 0, ev = 0;
        for(int i = 0; i < n; i++){
            cin >> a[i];
            sum += a[i];
            if(i%2) od += a[i];
            else ev += a[i];
        }
        if(n == 1){
            if(sum >= 2) cout << "Alice\n";
            else cout << "Bob\n";
            continue;
        }
        if(sum % 2){
            cout << "Bob\n";
            continue;
        }
        if(sum%4 == 0){
            if(od%2) cout << "Alice\n";
            else cout << "Bob\n";
        }
        else{
            if(od%2) cout << "Bob\n";
            else cout << "Alice\n";
        }
    }
}
Tester's code (C++)
#include <bits/stdc++.h>
using namespace std;

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        int a[n], sum[2];
        memset(sum, 0, sizeof(sum));
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
            sum[i&1]+=a[i];
        }
        if(n==1)
        {
            if(a[0]==1)
            cout<<"Bob\n";
            else
            cout<<"Alice\n";
        }
        else if((sum[0]+sum[1])&1)
        cout<<"Bob\n";
        else if((sum[0]+((sum[0]+sum[1])/2) - 1)&1)
        cout<<"Bob\n";
        else
        cout<<"Alice\n";
    }
}
Editorialist's code (Python)
for _ in range(int(input())):
    n = int(input())
    a = list(map(int, input().split()))
    s = sum(a)
    if n == 1:
        print('Alice' if s >= 2 else 'Bob')
        continue
    if s%2 == 1:
        print('Bob')
        continue
    req = s//2
    par = sum(a[::2]) % 2
    print('Alice' if par != req%2 else 'Bob')
4 Likes

u have written cannot be wins by Alice, but these are the cases in which he will wins

From the pattern above, it can be seen that if the initial state is 0 and X is odd, or if the initial state is 1 but X is even, this is impossible: after X moves, the state will be 1 which can never be Alice’s win.

1 Like

Yeah you’re right, even I was confused at first.

The mistake with the editorial is this line here

In particular, since she’ll make the last move, she needs to ensure that the parity is 0 after her last move.

See, Alice needs to make X moves to win.
However with every move Alice makes, Bob will also make a move and the editorial clearly explained that Bob’s moves will change the parity

However, what the editorial missed is that if we assume Alice, then that means Bob won’t be able to play his Xth move
Meaning that when Alice plays the Xth move, the parity actually won’t change

So actually we need to ensure that the parity is 0 after Alice’s second last move.
Cause after her last move, the parity will still remain 0 (Alice’s moves doesn’t effect parity) and Bob won’t be able to play making her win.

So yeah we actually need to make the decision based on the initial state and X-1, not X.

This is why the editorial mismatched the winning cases for Alice and Bob.

Hope the editorial is edited (hehehe editorial edited heheheeh)

1 Like

@neeraj321564 @dna5769
Thanks, fixed. I think I started out writing about Alice’s winning states first, then switched to losing states in my head and forgot to update things :sweat: .

No, actually: what I wrote in that part of the editorial remains correct.
The parity should be 0 after Alice’s last move because there will be no stones remaining; so the parity will be 1 after her second-last move (and then Bob flips it).

great question and editorial !

found a typo in the collapsible proof section

(just before her last move, she would have made an even number of moves; so Bob would’ve done the same and the current state will be )))); or

it should say 0 instead of )