题意
给定一个集合,问它的所有子集里,最小的没出现过的正整数之和是多少。
solution
先桶一遍。因为只有个数,所以每个区间的贡献(也就是每个区间没出现过的最小正整数)的取值范围必定在
。所以其实桶只需要统计
范围内就可以了。
那么只需要遍历桶:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 500010, mod = 20000311;
int n, cnt[N];
ll qkpow(ll a, ll b) {
ll ans = 1;
while (b) {
if (b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
int main() {
scanf("%d", &n);
for (int i = 1, x; i <= n; i++) {
scanf("%d", &x);
if (x <= n) ++cnt[x];
}
ll p = 1, q = n, ans = 0;
for (int i = 1; i <= n + 1; i++) {
q -= cnt[i]; //剩下的点
ans += p * qkpow(2, q) % mod * i, ans %= mod;
//加上所有不选值为i的点的区间的贡献
//剩下的每个点选或不选,所有的方案情况总数就是2**n
// i是价值 aka“遗憾”
p *= (qkpow(2, cnt[i]) - 1), p %= mod; //选上该点的所有区间数量
//不能不选,不能让它为空集
}
printf("%lld", ans);
return 0;
} 
京公网安备 11010502036488号