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;
}
posted @ 2018-09-12 07:57  King_George  阅读(124)  评论(0编辑  收藏  举报