Description:
Explanation:
The original intention of the questioner is to test inversion, and the result is not good enough to expect linear additive.
Recently, we have been practicing inclusion exclusion inversion, so at first glance, we can do it.
Let f(S)f(S) denote that the set of selected fruits is the scheme number of S, and g(S ′) g(S ′) denote that the selected fruits are the scheme number of subset of s'.
Obviously, g(S ′) g(S ′) is very easy to calculate. Remember that cntcnt cnt means that all fruits in the platter belong to the number of platters of S' set, then g(S ′) = Ckcntg(S ′) = Ccntk
The relationship between ff and G G is g(S ′) = ∑ S ∈ S ′ f(S)g(S ′) = ∑ S ∈ S ′ f(S)
According to the inversion routine, set the tolerance exclusion coefficient to hh
Then f(S) = ∑ S ′∈ Sg(S ′) * h(S ′) f(S) = ∑ S ′∈ Sg(S ′) * h(S ′)
Where h(S ′) h(S ′) is a function related to S', and gg is expanded to obtain:
f(S)=∑S′∈Sh(S′)∑S′′∈S′f(S′′)f(S)=∑S′∈Sh(S′)∑S″∈S′f(S″)
Let h(S ′) = (− 1)|S ′| h(S ′) = (− 1)|S ′| and then multiply the f(S)f(S) by (− 1)|S | (− 1)|S | to get ff, which will be simple later.
Violent enumeration will time out, so use wide search + pressure dp to optimize the transfer.
Code:
#include<bits/stdc++.h>
#define ll long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define min(a, b) ((a) < (b) ? (a) : (b))
#define fu(a) ((a) & 1 ? -1 : 1)
using namespace std;
const int mo = 998244353;
int n, m, k, x, y, a[20], b[20], a2[20], bz[100005];
ll c[100005][26], g[1 << 18], f[1 << 18][19], h[1 << 18], ans;
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;
}
int main() {
freopen("eat.in", "r", stdin);
freopen("eat.out", "w", stdout);
a2[0] = 1; fo(i, 1, 18) a2[i] = a2[i - 1] * 2;
scanf("%d %d %d", &n, &m, &k);
fo(i, 0, n) {
c[i][0] = 1;
fo(j, 1, min(i, k)) c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mo;
}
fo(i, 1, m) scanf("%d", &a[i]);
fo(i, 1, m) scanf("%d", &b[i]);
fo(i, 1, n) {
scanf("%d", &y);
fo(j, 1, y) {
scanf("%d", &x);
bz[i] |= a2[x - 1];
}
f[bz[i]][0] ++;
}
fo(i, 0, a2[m] - 1) {
fo(j, 0, m - 1) if(f[i][j]) {
fo(k, j, m - 1) if(!(i & a2[k]))
f[i | a2[k]][k + 1] += f[i][j];
}
int s1 = 0; fo(j, 0, m - 1) s1 += (i & a2[j]) > 0;
fo(j, 0, m) g[i] += f[i][j];
g[i] = c[g[i]][k] * fu(s1);
}
memset(f, 0, sizeof f);
fo(i, 0, a2[m] - 1) f[i][0] += g[i];
fo(i, 0, a2[m] - 1) {
fo(j, 0, m - 1) if(f[i][j]) {
fo(k, j, m - 1) if(!(i & a2[k]))
f[i | a2[k]][k + 1] = (f[i | a2[k]][k + 1] + f[i][j]) % mo;
}
int s1 = 0; fo(j, 0, m - 1) s1 += (i & a2[j]) > 0;
fo(j, 0, m) h[i] += f[i][j];
h[i] = (h[i] * fu(s1) % mo + mo) % mo;
ll s = 0;
fo(j, 0, m - 1) if(i & a2[j])
s += a[j + 1]; else s += b[j + 1];
ans = (ans + h[i] * (s % mo)) % mo;
}
ans = ans * ksm(c[n][k], mo - 2) % mo;
printf("%lld", ans);
}