公式

D - Stone XOR 解説 by en_translator


Considering which bags’ stones merge into one in the final state, we find that the answer to the problem is equal to that to the following:

consider dividing bags \(1\), bags \(2\), \(\ldots\), and bags \(N\) into several groups, and finding the total number of stones in the bags in each group. How many distinct integers can be the XOR (exclusive logical sum) of the counts?

The number of ways to divide \(N\) items into groups (where the items and groups are indistinguishable) is known as the Bell number \(B(N)\). The Bell number increases as \(N\) increases, and \( B(12)=4213597(\sim 4\times 10^6)\) for \(N=12\), so we can exhaustively enumerate them under the constraints \((2\leq N\leq 12)\) of this problem.

There are several ways for the exhaustive search; one is a DFS (Depth-First Search) based approach as follows.
Starting from the state with depth \(1\) and \(0\) groups, we perform the following operation.

When the current depth is \(d\) and there are \(k\) groups, perform the following operation for each \(1\leq i\leq k+1\) in order.

  • Let bag \(d\) belong to group \(i\).
    Here, if \(i=k+1\), it means we create a new group consisting only of bag \(d\).
  • If \(d=N\), record the XOR of the (group-wise) total numbers of stones in each group.
  • If \(d<N\), advance to the next depth (depth \((d+1)\)).
    Note that the number of groups has increased if \(i=k+1\).

After searching for all \(i\), go back to the previous depth (depth \((d-1)\)).
If \(d=1\), stop the search.

After the search ends, the sought answer is the number of distinct recorded integers.
This can be done in amortized \(O(1)\) time using a data structure that manages an unordered set (like set::unordered_set in C++). Thus, the complexity is \(O(NB(N))\), or \(O(B(N))\) if you compute the XOR in the course of the search.
This is fast enough to solve the problem.
If you record the XOR in an array and sort it at last, it may cost \(O(B(N)\log B(N))\) time, but such implementation will also finish within the time limit as long as the constant factor is small enough.

Sample code C++:

#include <bits/stdc++.h>
using namespace std;

int n;
long long a[12];
long long s[12];
long long val;
unordered_set<long long>st;

void dfs(int idx,int sz){
	for(int i=0;i<=sz;i++){
		val^=s[i];
		s[i]+=a[idx];
		val^=s[i];
		if(idx==n-1)st.insert(val);
		else if(i<sz)dfs(idx+1,sz);
		else dfs(idx+1,sz+1);
		val^=s[i];
		s[i]-=a[idx];
		val^=s[i];
	}
	return;
}


int main() {
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	for(int i=0;i<n;i++)s[i]=0;
	val=0;
	dfs(0,0);
	cout<<((int)(st.size()))<<endl;
	return 0;
}

投稿日時:
最終更新: