トピックリンク:HDU 5119
問題の説明
マットは、Nの友人を持っています。彼らは一緒にゲームをプレイされています。
Mattの友人のそれぞれは、マジックナンバーを持っています。ゲームでは、マットは、(ゼロになる可能性が)彼の友人の何人かを選択します。選択friends'magic数字のXOR(排他的論理和)合計はM以上である場合には、マットは勝ちます。
マットは勝つために、いくつかの方法を知りたいです。
入力
最初の行は、1つの整数含ま\(T \)テストケースの数を示し、。
各テストケースのために、最初の行は、2つの整数を含有する(N、M(1 \ルN \ル40、0 \ルル^ 6〜10 M \)\)\。
2行目、ある\(N \)整数\(K_I(0≤K_I≤10 ^ 6)\) 、を示す\(iは\)番目の友人のマジックナンバー。
出力
各テストケースのために、出力シングルライン「ケース#X:Y」、Xは(1から始まる)場合の数であり、yは、マットは、勝つことができるいくつかの方法を示しています。
サンプル入力
2
3 2
1 2 3
3 3
1 2 3
サンプル出力
Case #1: 4
Case #2: 2
ヒント
第1のサンプルでは、マットは、選択して勝つことができます。
数2と数1と友人と友人は、XOR和は3です。
数3と数1と友人と友人は、XOR和は2です。
XOR和2.番号を持つ友人が2です。
XOR和3.番号を持つ友人が故に3で、答えは4です。
ソース
ゲームを再現する(北課に感謝し、ひっくり返し) - 2014ACM / ICPCアジア北京駅
解決
問題の意味
所与\(N- \)番号\(K [I] \)より大きいかまたはそれに排他的に等しいいくつかの数取り、\(m個\)を、いくつかのエミュレートを見つけます。
考え
DPローリングバックパックアレー
セット\(DP [i]の[jを ] \) の元を表す\(私は\)番号と排他的論理和のために\(J \)をすべてエミュレート。状態遷移方程式である\([ - 1 I] [J] + DP [I - 1] DP [I] [J] DP = [J \ XOR \ K [I] \)。
唯一の現在の状態と前の状態、従って圧延配列を最適化するために使用することができるからです。
コード
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1 << 20;
ll dp[10][maxn];
ll k[50];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
for(int _ = 1; _ <= T; ++_) {
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; ++i) {
cin >> k[i];
}
for(int i = 1; i <= n; ++i) {
for(int j = 0; j < maxn; ++j) {
dp[i & 1][j] = dp[(i - 1) & 1][j] + dp[(i - 1) & 1][j ^ k[i]];
}
}
ll ans = 0;
for(int i = m; i < maxn; ++i) {
ans += dp[n & 1][i];
}
cout << "Case #" << _ << ": " << ans << endl;
}
return 0;
}