Problem:
D: Xor Array

問題文

整数 $N$ と $X$ が与えられます。
以下の条件を満たす長さ $N$ の数列の個数を $998244353$ で割った余りを求めてください。

数列は広義単調増加である。

数列の各要素は $0$ 以上 $X$ 以下である。

全ての要素の排他的論理和(xor)が $X$ である。

制約

$1 \leq N \leq 500$

$0 \leq X \leq 500$

$N$ と $X$ は整数である。

入力

入力は以下の形式で標準入力から与えられる。

$N$ $X$

出力

答えを出力せよ。

入力例1

2 3

出力例1

2

数列 $\{0,3\}$ と $\{1,2\}$ が条件を満たします。

入力例2

1 1

出力例2

1

数列 $\{1\}$ のみが条件を満たします。

入力例3

224 239

出力例3

400351036

Solution in C++14 (judge verdict: Accepted)

//#line 2 "SubstringQueries.cpp"

#define _CRT_SECURE_NO_WARNINGS

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <cstring>
#include <map>
#include <utility>
#include <set>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <list>
#include <random>
#include <algorithm>
#include <functional>
#include <sstream>
#include <complex>
#include <stack>
#include <queue>
#include <unordered_set>
#include <unordered_map>
#include <array>
#include <cassert>
#include <bitset>
#include <cstdint>
using namespace std;
using LL = long long;

int N, X;
const LL MOD = 998244353;
LL dp[515][515];
LL ndp[515][515];

int main() {
	cin >> N >> X;
	dp[0][0] = 1;
	for (int i = 0; i < N; ++i) {
		memset(ndp, 0, sizeof(ndp));
		//dpの累積和をとる
		for (int j = 0; j <= X; ++j) {
			for (int k = 0; k < 512; ++k) {
				dp[j + 1][k] += dp[j][k];
				dp[j + 1][k] %= MOD;
			}
		}
		//ndpに遷移
		for (int j = 0; j <= X; ++j) {
			for (int k = 0; k < 512; ++k) {
				ndp[j][k] = dp[j][j ^ k];
			}
		}
		//ndpをdpに移す
		for (int j = 0; j <= X; ++j) {
			for (int k = 0; k < 512; ++k) {
				dp[j][k] = ndp[j][k];
			}
		}
	}
	LL ans = 0;
	for (int j = 0; j <= X; ++j) {
		ans += dp[j][X];
		ans %= MOD;
	}
	cout << ans << endl;
	return 0;
}