题意
给定一个集合,问它的所有子集里,最小的没出现过的正整数之和是多少。
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; }