为防止广告,目前nocow只有登录用户能够创建新页面。如要创建页面请先登录/注册(新用户需要等待1个小时才能正常使用该功能)。

Sgu/434

来自NOCOW
< Sgu
跳转到: 导航, 搜索

若有k个数和为0,则可用至多k − 1次操作使得其全部变为0

所以此题就是把N个数分成尽量多的部分,使得每个部分的和都是0。

FS表示已选集合为S,最多能够将其分成多少组,使得至多一个组的和不为0(显然为GS)。

显然最后答案为N-F_{2^N-1}


#include <stdio.h>
#include <string.h>
 
int a[21], b[2097152], f[2097152], g[2097152];
int n;
 
long i, j, k = 0, l;
 
inline void max(int *a, const int b) { if (*a < b) *a = b; }
int main() {
	scanf("%d", &n);
	for (i = 0; i < n; ++i) scanf("%d", a + i);
	for (i = 0; i < n; ++i) scanf("%ld", &j), k += (a[i] -= j);
	if (k) return puts("-1"), 0;
 
	for (i = 0, k = 1; i < n; ++i, k <<= 1) b[k] = i;
	for (g[0] = 0, i = 1; i < k; ++i) j = i & -i, g[i] = g[i ^ j] + a[b[j]];
	memset(f, 0, sizeof f);
	for (i = 1; i < k; ++i)
		for (j = i; j; j ^= l) l = j & -j, max(f + i, f[i ^ l] + (g[i] == a[b[l]]));
 
	printf("%d", n - f[k - 1]);
	return 0;
}
个人工具