很有意思的一道题目。
直接去算这题话,因为分母会变,你会发现不管怎么样都要枚举顺序。
考虑把题目转换,变成分母不会变的,即对于一个已经删过的,我们不把它从分母中剔除,但是,每一次的选择需要一直选直到选了一个没有被删过的。
然后再考虑怎么计算,这时就可以容斥了:
1既然要最后删除,我们枚举一个集合S一定在它之后被删,其它的随意。
设\(sw\)为\(\sum_{i\in S}w[i]\),\(W=\sum_{i=1}^n w[i]\)
最后答案就是\(\sum_{S}(-1)^{|S|}\sum_{i=0}^{∞}({W-sw-w[1] \over W})^i*{w[1] \over W}\)
\(=\sum_S (-1)^{|S|}{W\over sw+w[1]}*{w[1]\over W}\)
\(=\sum_S (-1)^{|S|} {w[1] \over sw+w[1]}\)
用一个分治NTT优化一下背包就好了。
Code:
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i < _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;
const int mo = 998244353;
ll ksm(ll x, ll y) {
ll s = 1;
for(; y; y /= 2, x = x * x % mo)
if(y & 1) s = s * x % mo;
return s;
}
#define V vector<ll>
#define si size()
#define re resize
namespace ntt {
const int nm = 131072;
int r[nm]; ll w[nm], a[nm], b[nm];
void build() {
for(int i = 1; i < nm; i *= 2) {
w[i] = 1; ll v = ksm(3, (mo - 1) / 2 / i);
ff(j, 1, i) w[i + j] = w[i + j - 1] * v % mo;
}
}
void dft(ll *a, int n, int f) {
ff(i, 0, n) {
r[i] = r[i / 2] / 2 + (i & 1) * (n / 2);
if(i < r[i]) swap(a[i], a[r[i]]);
} ll b;
for(int i = 1; i < n; i *= 2) for(int j = 0; j < n; j += 2 * i) ff(k, 0, i)
b = a[i + j + k] * w[i + k], a[i + j + k] = (a[j + k] - b) % mo, a[j + k] = (a[j + k] + b) % mo;
if(f == -1) {
reverse(a + 1, a + n);
b = ksm(n, mo - 2);
ff(i, 0, n) a[i] = (a[i] + mo) * b % mo;
}
}
V operator * (V p, V q) {
int n0 = p.si + q.si - 1, n = 1;
while(n < n0) n *= 2;
ff(i, 0, n) a[i] = b[i] = 0;
ff(i, 0, p.si) a[i] = p[i];
ff(i, 0, q.si) b[i] = q[i];
dft(a, n, 1); dft(b, n, 1);
ff(i, 0, n) a[i] = a[i] * b[i] % mo;
dft(a, n, -1);
p.re(n0);
ff(i, 0, p.si) p[i] = a[i];
return p;
}
}
using ntt :: operator *;
const int N = 1e5 + 5;
int n, w[N];
V dg(int x, int y) {
if(x > y) {
V p; p.re(1); p[0] = 1;
return p;
}
if(x == y) {
V p; p.clear(); p.re(w[x] + 1);
p[0] = 1; p[w[x]] = -1;
return p;
}
int m = x + y >> 1;
return dg(x, m) * dg(m + 1, y);
}
int main() {
ntt :: build();
scanf("%d", &n);
fo(i, 1, n) scanf("%d", &w[i]);
V p = dg(2, n);
ll ans = 0;
ff(i, 0, p.si) ans = (ans + p[i] * ksm(i + w[1], mo - 2) % mo * w[1]) % mo;
ans = (ans % mo + mo) % mo;
pp("%lld\n", ans);
}
原文地址:https://www.cnblogs.com/coldchair/p/12620161.html
时间: 2024-10-26 11:57:39