/*
QUESTION 9: Odd Parts with Blocked Prefix Values
Problem Statement:
You are given a target sum X and a list of forbidden numbers.
Count how many sequences of positive odd integers have total sum exactly X.
While reading the sequence from left to right, no prefix sum is allowed to be equal
to any forbidden number.
Return the count modulo 998244353.
Hard Constraints:
1 <= X <= 1e18
1 <= number of forbidden values <= 100000
1 <= forbidden[i] <= 1e18
Example:
X = 6
forbidden = [1, 4]
Expected Output:
2
Explanation:
Valid sequences:
[3, 3]
[5, 1]
Invalid:
[1, 5] because prefix sum 1 is forbidden.
[3, 1, 1, 1] because prefix sum 4 is forbidden.
Brute Force:
Generate all ways to write X as a sum of positive odd numbers.
Check prefix sums for every sequence.
Time Complexity:
Exponential
Optimized Approach:
Let dp[s] be the number of ways to reach prefix sum s.
Since every added number is odd:
previous prefix and current prefix must have opposite parity.
Maintain:
evenSum = total ways ending at even prefix sums
oddSum = total ways ending at odd prefix sums
If a prefix sum is forbidden, skip it.
Because X can be very large, process long allowed ranges using matrix exponentiation.
Time Complexity:
O(N log N + N log X)
Space Complexity:
O(N)
*/
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
static const long long MOD = 998244353;
struct Matrix {
long long a[2][2];
Matrix(long long a00 = 1, long long a01 = 0,
long long a10 = 0, long long a11 = 1) {
a[0][0] = a00;
a[0][1] = a01;
a[1][0] = a10;
a[1][1] = a11;
}
};
Matrix multiply(Matrix x, Matrix y) {
Matrix res(0, 0, 0, 0);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
res.a[i][j] =
(res.a[i][j] + x.a[i][k] * y.a[k][j]) % MOD;
}
}
}
return res;
}
Matrix power(Matrix base, long long exp) {
Matrix res;
while (exp > 0) {
if (exp & 1) res = multiply(res, base);
base = multiply(base, base);
exp >>= 1;
}
return res;
}
pair<long long, long long> apply(Matrix m, long long evenSum, long long oddSum) {
long long newEven =
(m.a[0][0] * evenSum + m.a[0][1] * oddSum) % MOD;
long long newOdd =
(m.a[1][0] * evenSum + m.a[1][1] * oddSum) % MOD;
return {newEven, newOdd};
}
void processRange(long long l,
long long r,
long long& evenSum,
long long& oddSum) {
if (l > r) return;
long long len = r - l + 1;
Matrix oddStep(1, 0, 1, 1);
Matrix evenStep(1, 1, 0, 1);
Matrix pairStep;
Matrix singleStep;
if (l % 2 == 1) {
pairStep = multiply(evenStep, oddStep);
singleStep = oddStep;
} else {
pairStep = multiply(oddStep, evenStep);
singleStep = evenStep;
}
Matrix jump = power(pairStep, len / 2);
auto p = apply(jump, evenSum, oddSum);
evenSum = p.first;
oddSum = p.second;
if (len % 2 == 1) {
p = apply(singleStep, evenSum, oddSum);
evenSum = p.first;
oddSum = p.second;
}
}
long long countValidSequences(int N, long long X, vector<long long>& A) {
vector<long long> blocked;
for (long long v : A) {
if (v == X) return 0;
if (v > 0 && v < X) {
blocked.push_back(v);
}
}
sort(blocked.begin(), blocked.end());
blocked.erase(unique(blocked.begin(), blocked.end()), blocked.end());
long long evenSum = 1;
long long oddSum = 0;
long long current = 1;
for (long long b : blocked) {
processRange(current, b - 1, evenSum, oddSum);
current = b + 1;
}
processRange(current, X - 1, evenSum, oddSum);
if (X % 2 == 1) return evenSum;
return oddSum;
}
};
int main() {
Solution sol;
long long X = 6;
vector<long long> forbidden = {1, 4};
cout << sol.countValidSequences((int)forbidden.size(), X, forbidden) << endl;
return 0;
}
LyoKUVVFU1RJT04gOTogT2RkIFBhcnRzIHdpdGggQmxvY2tlZCBQcmVmaXggVmFsdWVzCgpQcm9ibGVtIFN0YXRlbWVudDoKWW91IGFyZSBnaXZlbiBhIHRhcmdldCBzdW0gWCBhbmQgYSBsaXN0IG9mIGZvcmJpZGRlbiBudW1iZXJzLgoKQ291bnQgaG93IG1hbnkgc2VxdWVuY2VzIG9mIHBvc2l0aXZlIG9kZCBpbnRlZ2VycyBoYXZlIHRvdGFsIHN1bSBleGFjdGx5IFguCgpXaGlsZSByZWFkaW5nIHRoZSBzZXF1ZW5jZSBmcm9tIGxlZnQgdG8gcmlnaHQsIG5vIHByZWZpeCBzdW0gaXMgYWxsb3dlZCB0byBiZSBlcXVhbAp0byBhbnkgZm9yYmlkZGVuIG51bWJlci4KClJldHVybiB0aGUgY291bnQgbW9kdWxvIDk5ODI0NDM1My4KCkhhcmQgQ29uc3RyYWludHM6CjEgPD0gWCA8PSAxZTE4CjEgPD0gbnVtYmVyIG9mIGZvcmJpZGRlbiB2YWx1ZXMgPD0gMTAwMDAwCjEgPD0gZm9yYmlkZGVuW2ldIDw9IDFlMTgKCkV4YW1wbGU6ClggPSA2CmZvcmJpZGRlbiA9IFsxLCA0XQoKRXhwZWN0ZWQgT3V0cHV0OgoyCgpFeHBsYW5hdGlvbjoKVmFsaWQgc2VxdWVuY2VzOgpbMywgM10KWzUsIDFdCgpJbnZhbGlkOgpbMSwgNV0gYmVjYXVzZSBwcmVmaXggc3VtIDEgaXMgZm9yYmlkZGVuLgpbMywgMSwgMSwgMV0gYmVjYXVzZSBwcmVmaXggc3VtIDQgaXMgZm9yYmlkZGVuLgoKQnJ1dGUgRm9yY2U6CkdlbmVyYXRlIGFsbCB3YXlzIHRvIHdyaXRlIFggYXMgYSBzdW0gb2YgcG9zaXRpdmUgb2RkIG51bWJlcnMuCkNoZWNrIHByZWZpeCBzdW1zIGZvciBldmVyeSBzZXF1ZW5jZS4KClRpbWUgQ29tcGxleGl0eToKRXhwb25lbnRpYWwKCk9wdGltaXplZCBBcHByb2FjaDoKTGV0IGRwW3NdIGJlIHRoZSBudW1iZXIgb2Ygd2F5cyB0byByZWFjaCBwcmVmaXggc3VtIHMuCgpTaW5jZSBldmVyeSBhZGRlZCBudW1iZXIgaXMgb2RkOgpwcmV2aW91cyBwcmVmaXggYW5kIGN1cnJlbnQgcHJlZml4IG11c3QgaGF2ZSBvcHBvc2l0ZSBwYXJpdHkuCgpNYWludGFpbjoKZXZlblN1bSA9IHRvdGFsIHdheXMgZW5kaW5nIGF0IGV2ZW4gcHJlZml4IHN1bXMKb2RkU3VtID0gdG90YWwgd2F5cyBlbmRpbmcgYXQgb2RkIHByZWZpeCBzdW1zCgpJZiBhIHByZWZpeCBzdW0gaXMgZm9yYmlkZGVuLCBza2lwIGl0LgoKQmVjYXVzZSBYIGNhbiBiZSB2ZXJ5IGxhcmdlLCBwcm9jZXNzIGxvbmcgYWxsb3dlZCByYW5nZXMgdXNpbmcgbWF0cml4IGV4cG9uZW50aWF0aW9uLgoKVGltZSBDb21wbGV4aXR5OgpPKE4gbG9nIE4gKyBOIGxvZyBYKQoKU3BhY2UgQ29tcGxleGl0eToKTyhOKQoqLwoKI2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgpjbGFzcyBTb2x1dGlvbiB7CnB1YmxpYzoKICAgIHN0YXRpYyBjb25zdCBsb25nIGxvbmcgTU9EID0gOTk4MjQ0MzUzOwoKICAgIHN0cnVjdCBNYXRyaXggewogICAgICAgIGxvbmcgbG9uZyBhWzJdWzJdOwoKICAgICAgICBNYXRyaXgobG9uZyBsb25nIGEwMCA9IDEsIGxvbmcgbG9uZyBhMDEgPSAwLAogICAgICAgICAgICAgICBsb25nIGxvbmcgYTEwID0gMCwgbG9uZyBsb25nIGExMSA9IDEpIHsKICAgICAgICAgICAgYVswXVswXSA9IGEwMDsKICAgICAgICAgICAgYVswXVsxXSA9IGEwMTsKICAgICAgICAgICAgYVsxXVswXSA9IGExMDsKICAgICAgICAgICAgYVsxXVsxXSA9IGExMTsKICAgICAgICB9CiAgICB9OwoKICAgIE1hdHJpeCBtdWx0aXBseShNYXRyaXggeCwgTWF0cml4IHkpIHsKICAgICAgICBNYXRyaXggcmVzKDAsIDAsIDAsIDApOwoKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IDI7IGkrKykgewogICAgICAgICAgICBmb3IgKGludCBqID0gMDsgaiA8IDI7IGorKykgewogICAgICAgICAgICAgICAgZm9yIChpbnQgayA9IDA7IGsgPCAyOyBrKyspIHsKICAgICAgICAgICAgICAgICAgICByZXMuYVtpXVtqXSA9CiAgICAgICAgICAgICAgICAgICAgICAgIChyZXMuYVtpXVtqXSArIHguYVtpXVtrXSAqIHkuYVtrXVtqXSkgJSBNT0Q7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHJldHVybiByZXM7CiAgICB9CgogICAgTWF0cml4IHBvd2VyKE1hdHJpeCBiYXNlLCBsb25nIGxvbmcgZXhwKSB7CiAgICAgICAgTWF0cml4IHJlczsKCiAgICAgICAgd2hpbGUgKGV4cCA+IDApIHsKICAgICAgICAgICAgaWYgKGV4cCAmIDEpIHJlcyA9IG11bHRpcGx5KHJlcywgYmFzZSk7CiAgICAgICAgICAgIGJhc2UgPSBtdWx0aXBseShiYXNlLCBiYXNlKTsKICAgICAgICAgICAgZXhwID4+PSAxOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHJlczsKICAgIH0KCiAgICBwYWlyPGxvbmcgbG9uZywgbG9uZyBsb25nPiBhcHBseShNYXRyaXggbSwgbG9uZyBsb25nIGV2ZW5TdW0sIGxvbmcgbG9uZyBvZGRTdW0pIHsKICAgICAgICBsb25nIGxvbmcgbmV3RXZlbiA9CiAgICAgICAgICAgIChtLmFbMF1bMF0gKiBldmVuU3VtICsgbS5hWzBdWzFdICogb2RkU3VtKSAlIE1PRDsKCiAgICAgICAgbG9uZyBsb25nIG5ld09kZCA9CiAgICAgICAgICAgIChtLmFbMV1bMF0gKiBldmVuU3VtICsgbS5hWzFdWzFdICogb2RkU3VtKSAlIE1PRDsKCiAgICAgICAgcmV0dXJuIHtuZXdFdmVuLCBuZXdPZGR9OwogICAgfQoKICAgIHZvaWQgcHJvY2Vzc1JhbmdlKGxvbmcgbG9uZyBsLAogICAgICAgICAgICAgICAgICAgICAgbG9uZyBsb25nIHIsCiAgICAgICAgICAgICAgICAgICAgICBsb25nIGxvbmcmIGV2ZW5TdW0sCiAgICAgICAgICAgICAgICAgICAgICBsb25nIGxvbmcmIG9kZFN1bSkgewogICAgICAgIGlmIChsID4gcikgcmV0dXJuOwoKICAgICAgICBsb25nIGxvbmcgbGVuID0gciAtIGwgKyAxOwoKICAgICAgICBNYXRyaXggb2RkU3RlcCgxLCAwLCAxLCAxKTsKICAgICAgICBNYXRyaXggZXZlblN0ZXAoMSwgMSwgMCwgMSk7CgogICAgICAgIE1hdHJpeCBwYWlyU3RlcDsKICAgICAgICBNYXRyaXggc2luZ2xlU3RlcDsKCiAgICAgICAgaWYgKGwgJSAyID09IDEpIHsKICAgICAgICAgICAgcGFpclN0ZXAgPSBtdWx0aXBseShldmVuU3RlcCwgb2RkU3RlcCk7CiAgICAgICAgICAgIHNpbmdsZVN0ZXAgPSBvZGRTdGVwOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHBhaXJTdGVwID0gbXVsdGlwbHkob2RkU3RlcCwgZXZlblN0ZXApOwogICAgICAgICAgICBzaW5nbGVTdGVwID0gZXZlblN0ZXA7CiAgICAgICAgfQoKICAgICAgICBNYXRyaXgganVtcCA9IHBvd2VyKHBhaXJTdGVwLCBsZW4gLyAyKTsKCiAgICAgICAgYXV0byBwID0gYXBwbHkoanVtcCwgZXZlblN1bSwgb2RkU3VtKTsKICAgICAgICBldmVuU3VtID0gcC5maXJzdDsKICAgICAgICBvZGRTdW0gPSBwLnNlY29uZDsKCiAgICAgICAgaWYgKGxlbiAlIDIgPT0gMSkgewogICAgICAgICAgICBwID0gYXBwbHkoc2luZ2xlU3RlcCwgZXZlblN1bSwgb2RkU3VtKTsKICAgICAgICAgICAgZXZlblN1bSA9IHAuZmlyc3Q7CiAgICAgICAgICAgIG9kZFN1bSA9IHAuc2Vjb25kOwogICAgICAgIH0KICAgIH0KCiAgICBsb25nIGxvbmcgY291bnRWYWxpZFNlcXVlbmNlcyhpbnQgTiwgbG9uZyBsb25nIFgsIHZlY3Rvcjxsb25nIGxvbmc+JiBBKSB7CiAgICAgICAgdmVjdG9yPGxvbmcgbG9uZz4gYmxvY2tlZDsKCiAgICAgICAgZm9yIChsb25nIGxvbmcgdiA6IEEpIHsKICAgICAgICAgICAgaWYgKHYgPT0gWCkgcmV0dXJuIDA7CgogICAgICAgICAgICBpZiAodiA+IDAgJiYgdiA8IFgpIHsKICAgICAgICAgICAgICAgIGJsb2NrZWQucHVzaF9iYWNrKHYpOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBzb3J0KGJsb2NrZWQuYmVnaW4oKSwgYmxvY2tlZC5lbmQoKSk7CiAgICAgICAgYmxvY2tlZC5lcmFzZSh1bmlxdWUoYmxvY2tlZC5iZWdpbigpLCBibG9ja2VkLmVuZCgpKSwgYmxvY2tlZC5lbmQoKSk7CgogICAgICAgIGxvbmcgbG9uZyBldmVuU3VtID0gMTsKICAgICAgICBsb25nIGxvbmcgb2RkU3VtID0gMDsKCiAgICAgICAgbG9uZyBsb25nIGN1cnJlbnQgPSAxOwoKICAgICAgICBmb3IgKGxvbmcgbG9uZyBiIDogYmxvY2tlZCkgewogICAgICAgICAgICBwcm9jZXNzUmFuZ2UoY3VycmVudCwgYiAtIDEsIGV2ZW5TdW0sIG9kZFN1bSk7CiAgICAgICAgICAgIGN1cnJlbnQgPSBiICsgMTsKICAgICAgICB9CgogICAgICAgIHByb2Nlc3NSYW5nZShjdXJyZW50LCBYIC0gMSwgZXZlblN1bSwgb2RkU3VtKTsKCiAgICAgICAgaWYgKFggJSAyID09IDEpIHJldHVybiBldmVuU3VtOwogICAgICAgIHJldHVybiBvZGRTdW07CiAgICB9Cn07CgppbnQgbWFpbigpIHsKICAgIFNvbHV0aW9uIHNvbDsKCiAgICBsb25nIGxvbmcgWCA9IDY7CiAgICB2ZWN0b3I8bG9uZyBsb25nPiBmb3JiaWRkZW4gPSB7MSwgNH07CgogICAgY291dCA8PCBzb2wuY291bnRWYWxpZFNlcXVlbmNlcygoaW50KWZvcmJpZGRlbi5zaXplKCksIFgsIGZvcmJpZGRlbikgPDwgZW5kbDsKCiAgICByZXR1cm4gMDsKfQ==