Loading

[NOIP2021] 数列

题目描述

给定整数 \(n, m, k\),和一个长度为 \(m + 1\) 的正整数数组 \(v_0, v_1, \ldots, v_m\)

对于一个长度为 \(n\),下标从 \(1\) 开始且每个元素均不超过 \(m\) 的非负整数序列 \(\{a_i\}\),我们定义它的权值为 \(v_{a_1} \times v_{a_2} \times \cdots \times v_{a_n}\)

当这样的序列 \(\{a_i\}\) 满足整数 \(S = 2^{a_1} + 2^{a_2} + \cdots + 2^{a_n}\) 的二进制表示中 \(1\) 的个数不超过 \(k\) 时,我们认为 \(\{a_i\}\) 是一个合法序列。

计算所有合法序列 \(\{a_i\}\) 的权值和对 \(998244353\) 取模的结果。

数据范围

对所有测试点保证 \(1 \leq k \leq n \leq 30\)\(0 \leq m \leq 100\)\(1 \leq v_i < 998244353\)

solution

按位 \(dp\)

由低位向高位考虑 \(S\)

\(f_{i, j, k, p}\) 表示讨论了 \(S\) 从低到高的前 \(i\) 位,已经确定了 \(j\) 个序列 \(a\) 中的元素,\(S\) 从低到高前 \(i\) 位中有 \(k\)\(1\) ,要向当前讨论位的下一位进位 \(p\)

转移时枚举 \(a_i\) 中有多少个 \(i\)

\[f(i + 1,~ j + t,~ k + (t + p)~mod~2, ~\lfloor{\frac{t + p}{2}}\rfloor ) = f(i, ~j,~ k, ~p)\times v_i^t \times {n-j\choose t} \]

注意还有 \(m\) 位后面的 \(1\) 也要统计

复杂度 \(O(n^4m)\)

code

#include <cstdio>
#include <iostream>
using namespace std;
typedef long long ll;
const ll mod = 998244353;

ll ans, v[105], f[105][35][35][16], fac[105][35];

ll C[35][35];
inline void init(int n) {
	for (int i = 0; i <= n; i++) C[i][0] = 1;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= i; j++) C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod;
}

inline int popcnt(int n) {
	int res = 0;
	while (n) res += n & 1, n >>= 1;
	return res;
}

int main() {
	init(30);
	int n, m, K;
	scanf("%d %d %d", &n, &m, &K);
	for (int i = 0; i <= m; i++) {
		scanf("%lld", &v[i]);
		fac[i][0] = 1;
		for (int j = 1; j <= n; j++) fac[i][j] = fac[i][j - 1] * v[i] % mod;
	}
	f[0][0][0][0] = 1;
	for (int i = 0; i <= m; i++)
		for (int j = 0; j <= n; j++)
			for (int k = 0; k <= K; k++)
				for (int p = 0; p <= n >> 1; p++)
					for (int t = 0; t <= n - j; t++) f[i + 1][j + t][k + (t + p & 1)][t + p >> 1] = (f[i + 1][j + t][k + (t + p & 1)][t + p >> 1] + f[i][j][k][p] * fac[i][t] % mod * C[n - j][t] % mod) % mod;
	for (int k = 0; k <= K; k++)
		for (int p = 0; p <= n >> 1; p++)
			if (k + popcnt(p) <= K) ans = (ans + f[m + 1][n][k][p]) % mod;
	printf("%lld", ans);
	return 0;
}
posted @ 2022-10-25 11:12  Dita  阅读(122)  评论(1编辑  收藏  举报