# [ZJOI2019]开关

## 题解

$P=\sum p_i$

$F(x)=\prod \frac {e^{\frac {p_i}Px}+e^{-\frac {p_i}Px}(-1)^{s_i}}2$

$G(x)=\prod \frac{e^{\frac {p_i}Px}+e^{-\frac {p_i}Px}}2$

\begin{aligned} F(x)&=\sum_{i=-P}^Pa_ie^{\frac iPx}\\ &=\sum_{i=-P}^Pa_i\sum_{j\geq 0}\frac {(\frac {xi}P)^j}{j!} \end{aligned}

$j!$去掉后直接等比数列求和：

$f(x)=\sum_{i=-P}^P\frac {a_i}{1-\frac {xi}{P}}$

## 代码

#include <bits/stdc++.h>
using namespace std;
int gi() {
int res = 0, w = 1;
char ch = getchar();
while (ch != '-' && !isdigit(ch)) ch = getchar();
if (ch == '-') w = -1, ch = getchar();
while (isdigit(ch)) res = res * 10 + ch - '0', ch = getchar();
return res * w;
}
const int Mod = 998244353;
int fpow(int x, int y) {
int res = 1;
while (y) {
if (y & 1) res = 1ll * res * x % Mod;
x = 1ll * x * x % Mod, y >>= 1;
}
return res;
}
const int MAX_N = 1e5 + 5;
void Pls(int &x, int y) { x += y; if (x >= Mod) x -= Mod; }
int N, s[MAX_N], p[MAX_N], P;
int f[MAX_N], g[MAX_N], tf[MAX_N], tg[MAX_N];
int main () {
#ifndef ONLINE_JUDGE
freopen("cpp.in", "r", stdin);
#endif
N = gi();
for (int i = 1; i <= N; i++) s[i] = gi();
for (int i = 1; i <= N; i++) p[i] = gi(), P += p[i];
f[P] = g[P] = 1;
for (int i = 1, k = 0; i <= N; i++) {
k += p[i];
for (int j = 0; j <= P << 1; j++) tf[j] = tg[j] = 0;
for (int j = 0; j <= P << 1; j++) {
if (j - p[i] >= 0) Pls(tf[j], f[j - p[i]]);
if (j + p[i] <= P << 1) Pls(tf[j], s[i] ? (-f[j + p[i]] + Mod) : f[j + p[i]]);
}
for (int j = 0; j <= P << 1; j++) {
if (j - p[i] >= 0) Pls(tg[j], g[j - p[i]]);
if (j + p[i] <= P << 1) Pls(tg[j], g[j + p[i]]);
}
for (int j = 0; j <= P << 1; j++) f[j] = tf[j], g[j] = tg[j];
}
int ans = 0, inv = fpow(P, Mod - 2);
for (int i = -P; i < P; i++) Pls(ans, 1ll * f[i + P] * fpow(1ll * (i + Mod) * inv % Mod - 1, Mod - 2) % Mod);
for (int i = -P; i < P; i++) Pls(ans, Mod - 1ll * g[i + P] * fpow(1ll * (i + Mod) * inv % Mod - 1, Mod - 2) % Mod);
printf("%d\n", ans);
return 0;
}

posted @ 2020-10-21 21:28  heyujun  阅读(148)  评论(1编辑  收藏  举报