Welcome to Subscribe On Youtube
4002. Count Valid Sequences
Description
You are given two positive integers n and k.
A valid sequence is a sequence of k positive integers such that:
- The sum of all integers in the sequence is equal to
n. - The product of all integers in the sequence is even.
Return the number of valid sequences. Since the answer may be very large, return it modulo 109 + 7.
Two sequences are considered different if they differ at any index. For example, [1, 1, 2] and [1, 2, 1] are considered different sequences.
Example 1:
Input: n = 5, k = 3
Output: 3
Explanation:
The sequences of length k = 3 whose sum is 5 are:
| Sequence | Product | Parity |
|---|---|---|
[1, 1, 3] |
1 * 1 * 3 = 3 |
Odd |
[1, 2, 2] |
1 * 2 * 2 = 4 |
Even |
[2, 1, 2] |
2 * 1 * 2 = 4 |
Even |
[2, 2, 1] |
2 * 2 * 1 = 4 |
Even |
[1, 3, 1] |
1 * 3 * 1 = 3 |
Odd |
[3, 1, 1] |
3 * 1 * 1 = 3 |
Odd |
There are 3 sequences with an even product, thus the answer is 3.
Example 2:
Input: n = 3, k = 2
Output: 2
Explanation:
The sequences of length k = 2 whose sum is 3 are:
| Sequence | Product | Parity |
|---|---|---|
[1, 2] |
1 * 2 = 2 |
Even |
[2, 1] |
2 * 1 = 2 |
Even |
There are 2 sequences with an even product, thus the answer is 2.
Example 3:
Input: n = 5, k = 5
Output: 0
Explanation:
The only possible sequence of length k = 5 whose sum is 5 is [1, 1, 1, 1, 1], which has an odd product. Thus, the answer is 0.
Constraints:
1 <= n <= 5 * 1051 <= k <= n
Solutions
Solution 1: Combinatorics
The number of ordered ways to write $n$ as a sum of $k$ positive integers is $\binom{n-1}{k-1}$. An even product means “at least one even number”; the complement is “all odd”.
Therefore the answer is:
\[\binom{n-1}{k-1} - \textit{(number of all-odd sequences)}\]If every number is odd, write the $i$-th number as $2a_i + 1$ ($a_i \ge 0$). Then:
\[\sum_{i=1}^{k}(2a_i + 1) = n \implies \sum_{i=1}^{k} a_i = \frac{n-k}{2}\]All-odd sequences exist only when $n$ and $k$ have the same parity (i.e., $n + k$ is even), and their count is $\binom{\frac{n+k}{2}-1}{k-1}$; otherwise the count is $0$.
After precomputing factorials and modular inverses, each combination can be evaluated in $O(1)$. Return the answer modulo $10^9+7$.
The time complexity is $O(N + \log M)$ for preprocessing, and the space complexity is $O(N)$, where $N = 5 \times 10^5$ and $M = 10^9+7$. Each query is $O(1)$.
-
class Solution { static final int MX = 500001; static final long MOD = 1000000007L; static long[] f = new long[MX]; static long[] g = new long[MX]; static { f[0] = 1; g[0] = 1; for (int i = 1; i < MX; i++) { f[i] = f[i - 1] * i % MOD; g[i] = pow(f[i], MOD - 2); } } static long pow(long a, long b) { long res = 1; while (b > 0) { if ((b & 1) == 1) { res = res * a % MOD; } a = a * a % MOD; b >>= 1; } return res; } static long comb(int n, int k) { return f[n] * g[k] % MOD * g[n - k] % MOD; } public int countValidSequences(int n, int k) { long ans = comb(n - 1, k - 1); if ((n + k) % 2 == 0) { ans = (ans - comb((n + k) / 2 - 1, k - 1) + MOD) % MOD; } return (int) ans; } } -
const int MX = 500001; const long long MOD = 1000000007LL; long long f[MX]; long long g[MX]; long long qpow(long long a, long long b) { long long res = 1; while (b > 0) { if (b & 1) { res = res * a % MOD; } a = a * a % MOD; b >>= 1; } return res; } int init = []() { f[0] = 1; g[0] = 1; for (int i = 1; i < MX; i++) { f[i] = f[i - 1] * i % MOD; g[i] = qpow(f[i], MOD - 2); } return 0; }(); long long comb(int n, int k) { return f[n] * g[k] % MOD * g[n - k] % MOD; } class Solution { public: int countValidSequences(int n, int k) { long long ans = comb(n - 1, k - 1); if ((n + k) % 2 == 0) { ans = (ans - comb((n + k) / 2 - 1, k - 1) + MOD) % MOD; } return (int) ans; } }; -
MX = 5 * 10**5 + 1 MOD = 10**9 + 7 f = [1] * MX g = [1] * MX for i in range(1, MX): f[i] = f[i - 1] * i % MOD g[i] = pow(f[i], MOD - 2, MOD) def comb(n: int, k: int) -> int: return f[n] * g[k] * g[n - k] % MOD class Solution: def countValidSequences(self, n: int, k: int) -> int: ans = comb(n - 1, k - 1) if (n + k) % 2 == 0: ans = (ans - comb((n + k) // 2 - 1, k - 1)) % MOD return ans -
const MX = 500001 const MOD int64 = 1000000007 var f [MX]int64 var g [MX]int64 func init() { f[0] = 1 g[0] = 1 for i := 1; i < MX; i++ { f[i] = f[i-1] * int64(i) % MOD g[i] = pow(f[i], MOD-2) } } func pow(a, b int64) int64 { res := int64(1) for b > 0 { if b&1 == 1 { res = res * a % MOD } a = a * a % MOD b >>= 1 } return res } func comb(n, k int) int64 { return f[n] * g[k] % MOD * g[n-k] % MOD } func countValidSequences(n int, k int) int { ans := comb(n-1, k-1) if (n+k)%2 == 0 { ans = (ans - comb((n+k)/2-1, k-1) + MOD) % MOD } return int(ans) } -
const MX = 500001; const MOD = 1000000007n; const f: bigint[] = new Array(MX).fill(1n); const g: bigint[] = new Array(MX).fill(1n); function pow(a: bigint, b: bigint): bigint { let res = 1n; while (b > 0n) { if (b & 1n) { res = (res * a) % MOD; } a = (a * a) % MOD; b >>= 1n; } return res; } for (let i = 1; i < MX; i++) { f[i] = (f[i - 1] * BigInt(i)) % MOD; g[i] = pow(f[i], MOD - 2n); } function comb(n: number, k: number): bigint { return (((f[n] * g[k]) % MOD) * g[n - k]) % MOD; } function countValidSequences(n: number, k: number): number { let ans = comb(n - 1, k - 1); if ((n + k) % 2 === 0) { ans = (ans - comb((n + k) / 2 - 1, k - 1) + MOD) % MOD; } return Number(ans); }