2018 Multi-University Training Contest 2 08
题意
给 \(10\) 次多项式 \(F(x)\)。
问 \(F(x)^n\) 有多少项系数是奇数。
\(1\ \leq\ n\ \ leq\ 10^9\)
做法1
考虑问题 \(F(x)^n\ G(x)\) 有多少项是奇数。
定义 \(A(x),\ B(x)\),满足 \([x^i]A(x)\ =\ [x^{2i}]G(x),\ [x^i]B(x)\ =\ [x^{2i\ +\ 1}]G(x)\)。
则有 \(F(x)^n\ G(x)\ =\ F(x)^n(A(x^2)\ +\ B(x^2)\ x)\)。
由于模 \(2\) 意义下 \(F(x)^2\ =\ F(x^2)\),所以若 \(n\ =\ 2k\)则有 \(F(x)^{2k}\ G(x)\ =\ F(x)^{2k}\ A(x^2)\ +\ F(x)^2k\ B(x^2)\ x\ =\ F(x^2)^k\ A(x^2)\ +\ F(x^2)^k\ B(x^2)\ x\)。
所以其奇数项次数 \(\ =\ F(x)^k\ A(x)\) 的奇数项次数 \(+\ F(x)^k\ B(x)\)。
如果 \(n\) 为奇数,将 \(G(x)\) 乘上 \(F(x)\) 即可。
代码
#include <bits/stdc++.h>
#ifdef DEBUG
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif
#ifdef __WIN32
#define LLFORMAT "I64"
#else
#define LLFORMAT "ll"
#endif
using namespace std;
const int maxn = (1 << 11) | 10, mod = 998244353;
int n, x;
map<pair<int, long long>, int> f;
int F(int n, long long g) {
if(!n) return __builtin_popcount(g);
pair<int, long long> foo = make_pair(n, g);
if(f.count(foo)) return f[foo];
if(n & 1) {
long long t = 0;
for (int i = 0; i <= 10; ++i) if((x >> i) & 1) t ^= (g << i);
g = t;
--n;
}
long long a = 0, b = 0, s = 1;
for (int i = 0; s <= g; ++i, (s <<= 1)) if(g & s) {
if(i & 1) b |= (1ll << (i >> 1));
else a |= (1ll << (i >> 1));
}
n >>= 1;
return f[foo] = (F(n, a) + F(n, b)) % mod;
}
void solve() {
f.clear(); x = 1;
for (int y, i = 1; i <= 10; ++i) {
scanf("%d", &y);
x |= ((y & 1) << i);
}
printf("%d\n", F(n, 1));
return;
}
int main() {
while(scanf("%d", &n) == 1) solve();
return 0;
}