Given an array, arr, of length n, find how many subsets of arr there are such that XOR(^) of those subsets is equal to a given number, ans.
I have this dp approach but is there a way to improve its time complexity. ans is always less than 1024.
Here ans is the no. such that XOR(^) of the subsets is equal to it.
arr[n] contains all the numbers
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for(i = 1; i <= n; i++){
for(j = 0; j < 1024; j++) {
dp[i][j] = (dp[i-1][j] + dp[i-1][j^arr[i]]);
}
}
cout << (dp[n][ans]);
From user3386109's comment, building on top of your code:
/* Warning: Untested */
int counts[1024] = {0}, ways[1024];
for(int i = 1; i <= n; ++i) counts[ arr[i] ] += 1;
for(int i = 0; i <= 1024; ++i) {
const int z = counts[i];
// Look for overflow here
ways[i] = z == 0 ?
0 :
(int)(1U << (z-1));
}
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for(i = 1; i <= 1024; i++){
for(j = 0; j < 1024; j++) {
// Check for overflow
const int howmany = ways[i] * dp[i-1][j];
dp[i][j] += howmany;
dp[i][j^i] += howmany;
}
}
cout << (dp[1024][ans]);
For calculating odd_ and even_, you can also use the following:
nc0+nc2+... = nc1+nc3... = 2n-1
Because number of ways to select odd items = number of ways to reject odd items = number of ways to select even numbers
You can also optimize the space by keeping just 2 columns of dp arrays and reusing them as dp[i-2][x] are discarded.
The Idea behind dynamic programming is, to (1) never compute the same result twice and (2) only compute results at demand and not precompute the whole thing as you do it.
So there is a solution needed for solve(arr, n, ans) with ans < 1024, n < 1000000 and arr = array[n]. The idea of having dp[n][ans] holding the number of results is reasonable, so dp size is needed as dp = array[n+1][1024]. What we need is a way to distinguish between not yet computed results and available results. So memset(dp, -1, sizeof(dp)) and then as you already did dp[0][0] = 1
solve(arr, n, ans):
if (dp[n][ans] == -1)
if (n == 0) // and ans != 0 since that was initialized already
dp[n][ans] = 0
else
// combine results with current and without current array element
dp[n][ans] = solve(arr + 1, n - 1, ans) + solve(arr + 1, n - 1, ans XOR arr[0])
return dp[n][ans]
The advantage is, that your dp array is only partially computed on the way to your solution, so this might save some time.
Depending on the stack size and n, it might be necessary to translate this from a recursive to an iterative solution
来源:https://stackoverflow.com/questions/34148742/given-an-array-of-length-n-find-number-of-subsets-where-xor-of-a-subset-is-equa