vector<int> a(m); bool possible = true; for (int i = 0; i < m; ++i) { cin >> a[i]; // 如果汐被强制要求选大于 2n 的牌,则她在前 2n 里的牌数不足 n 张,必然无法挡住风子前 n 小的牌 if (a[i] > 2 * n) { possible = false; } }
if (!possible) { cout << 0 << "\n"; return; }
// 标记哪些数字是汐必须选的(即折线图中必须向右上走的位置) vector<bool> is_fixed(2 * n + 1, false); for (int i = 0; i < m; ++i) { is_fixed[a[i]] = true; }
using ll = longlong; using ull = unsignedlonglong; using ld = longdouble; using pii = pair<int, int>; using pll = pair<ll, ll>; using vi = vector<int>; using vl = vector<ll>; using vii = vector<pii>; using vll = vector<pll>;
#define endl '\n' #define pb push_back #define eb emplace_back #define mp make_pair #define fi first #define se second #define all(x) (x).begin(), (x).end() #define rall(x) (x).rbegin(), (x).rend() #define sz(x) (int)(x).size() #define mem(a, b) memset(a, b, sizeof(a)) #define rep(i, a, n) for (int i = a; i < n; i++) #define per(i, a, n) for (int i = n - 1; i >= a; i--) #define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0) #define clock cerr << "Time elapsed: " << (double)clock() / CLOCKS_PER_SEC << " s.\n"
// 快速幂(带模):返回 a^b mod template <typename T> inline T qpow(T a, T b, T mod){ T res = 1; while (b) { if (b & 1) { res = res * a % mod; } a = a * a % mod; b >>= 1; } return res; }
// 快速幂(不带模):返回 a^b template <typename T> inline T qpow(T a, T b){ T res = 1; while (b) { if (b & 1) { res = res * a; } a = a * a; b >>= 1; } return res; }
voidsolve(){ ll n, m; cin >> n >> m;
vl a(m);
// possible = false 表示存在无法满足的必选数,答案直接是 0 bool possible = true;
// constraint[v] = true 表示值 v 是「必须选入手牌」的数 // 只需要开到 2n-1(下标 0 .. 2n-1),因为更大的值不可能出现在必胜手牌里 vl constraint(2 * n, false);
for (int i = 0; i < m; ++i) { cin >> a[i]; if (a[i] > 2 * n - 1) { // 必胜条件要求 s_n <= 2n-1,即手牌中最大的数也不能超过 2n-1。 // 现在被强制要选一个超过 2n-1 的数,必胜手牌不存在。 // 注意:这里不能直接 return,必须把剩下的 m 个数读完,否则输入流会错位。 possible = false; } else { constraint[a[i]] = true; } }
// 转移 2:不选 v,选中数量不变。只有 v 不是必选数时才允许 if (!need) { next[c] = (next[c] + dp[c]) % MOD; } }
// 施加必胜条件:v 为奇数时,写 v = 2k-1,则 k = (v+1)/2。 // 条件 s_k <= 2k-1 等价于「前缀 [1, 2k-1] 里至少已经选了 k 个数」, // 所以把所有 c < k 的状态判死(清零)。 // v 为偶数时不产生新约束,无需处理。 if (v % 2 == 1) { int k = (v + 1) / 2; for (int c = 0; c < k; ++c) { next[c] = 0; } }