UOJ692 【UR #23】民意调查 【背包,dp】

给定 \(n\) 个正整数 \(a_1,\cdots,a_n\),求大小为奇数的非空子集中,平均数 \(<\) 中位数的数量 \(\bmod 998\,244\,353\)

\(n\le 70\)\(a_i\le V\le 800\)

先排个序从小到大选数,记一下个数以及总和进行一个 dp 就可以了!时间复杂度 \(\mathcal O(n^3V)\),空间复杂度 \(\mathcal O(n^2V)\)

#include<bits/stdc++.h>
const int N = 40, M = 33333, mod = 998244353;
int n, V, a[N<<1], f[N][M], g[N][M];
void upd(int &a, int b){a += b; if(a >= mod) a -= mod;}
int main(){
	std::ios::sync_with_stdio(0);
	std::cin >> n >> V;
	for(int i = 0;i < n;++ i) std::cin >> a[i];
	std::sort(a, a + n); **f = 1;
	for(int i = 0;i < n;++ i){
		for(int j = 1;j <= i && j <= n - i;++ j)
			for(int k = a[i];k < M;++ k)
				upd(g[j - 1][k - a[i]], g[j][k]);
		for(int j = std::min(i, n - i);j >= 0;-- j){
			for(int k = 0;k + a[i] < M;++ k)
				upd(f[j + 1][k + a[i]], f[j][k]);
			int ei = 2 * j * a[i] - 1;
			for(int k = std::min(ei, M - 1);k >= 0;-- k)
				upd(g[j][ei - k], f[j][k]);
		}
	}
	int ans = 0;
	for(int i = 0;i < M;++ i) upd(ans, g[0][i]);
	printf("%d\n", ans);
}
posted @ 2022-08-05 08:55  mizu164  阅读(65)  评论(0)    收藏  举报