Luogu5339 [TJOI2019] sing, dance, rap and basketball [generating function, NTT]

This question was to see when my brain might look like this:

My left brain has nothing right, and my right brain has nothing left.

In short, see the "no chicken you're so beautiful," the kind you want to direct inclusion and exclusion, translates to "at least $ i $ chicken you're so beautiful."

See the arrangement, which directly want to generate exponential function.

设$m=\min(\frac{n}{4},a,b,c,d)$

We use the same years bundle method, the chicken you're so beautiful as a whole consider that the $ n-3i $ $ i $ th element selected as a chicken you're so beautiful, and then the four other full order.

$$ans=\sum_{i=0}^m(-1)^i(n-4i)!\binom{n-3i}{i}\sum_{i_1\leq a-i}\sum_{i_2\leq b-i}\sum_{i_3\leq c-i}\sum_{i_4\leq d-i}\frac{1}{\prod i_j!}[\sum i_j=n-4i]$$

$$\sum_{i=0}^m(-1)^i\frac{(n-3i)!}{i!}\sum_{i_1\leq a-i}\sum_{i_2\leq b-i}\sum_{i_3\leq c-i}\sum_{i_4\leq d-i}\frac{1}{\prod i_j!}[\sum i_j=n-4i]$$

It can be calculated using the back of a long list of NTT optimization.

Time complexity $ O (n ^ 2 \ log n) $, I heard that there is a direct dp of $ O (n ^ 2) $ approach, but the generating function approach should be no more than the brain.

 1 #include<bits/stdc++.h>
 2 #define Rint register int
 3 using namespace std;
 4 typedef long long LL;
 5 const int N = 1 << 12, mod = 998244353, g = 3, gi = 332748118;
 6 inline int kasumi(int a, int b){
 7     int res = 1;
 8     while(b){
 9         if(b & 1) res = (LL) res * a % mod;
10         a = (LL) a * a % mod;
11         b >>= 1;
12     }
13     return res;
14 }
15 int fac[N], inv[N];
16 inline void init(int n){
17     fac[0] = 1;
18     for(Rint i = 1;i <= n;i ++) fac[i] = (LL) i * fac[i - 1] % mod;
19     inv[n] = kasumi(fac[n], mod - 2);
20     for(Rint i = n;i;i --) inv[i - 1] = (LL) inv[i] * i % mod;
21 }
22 int rev[N];
23 inline int calrev(int n){
24     int limit = 1, L = -1;
25     while(limit <= n){limit <<= 1; L ++;}
26     for(Rint i = 0;i < limit;i ++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << L);
27     return limit;
28 }
29 inline void NTT(int *A, int limit, int type){
30     for(Rint i = 0;i < limit;i ++) if(i < rev[i]) swap(A[i], A[rev[i]]);
31     for(Rint mid = 1;mid < limit;mid <<= 1){
32         int Wn = kasumi(type == 1 ? g : gi, (mod - 1) / (mid << 1));
33         for(Rint j = 0;j < limit;j += mid << 1){
34             int w = 1;
35             for(Rint k = 0;k < mid;k ++, w = (LL) w * Wn % mod){
36                 int x = A[j + k], y = (LL) w * A[j + k + mid] % mod;
37                 A[j + k] = (x + y) % mod;
38                 A[j + k + mid] = (x - y + mod) % mod;
39             }
40         }
41     }
42     if(type == -1){
43         int inv = kasumi(limit, mod - 2);
44         for(Rint i = 0;i < limit;i ++)
45             A[i] = (LL) A[i] * inv % mod;
46     }
47 }
48 int n, a, b, c, d, m, ans, A[N], B[N], C[N], D[N];
49 int main(){
50     scanf("%d%d%d%d%d", &n, &a, &b, &c, &d);
51     init(a + b + c + d);
52     m = min(n >> 2, min(min(a, b), min(c, d)));
53     for(Rint i = 0;i <= m;i ++){
54         int limit = calrev(a + b + c + d - (i << 2));
55         for(Rint j = 0;j < limit;j ++){
56             A[j] = inv[j] * (j <= a - i);
57             B[j] = inv[j] * (j <= b - i);
58             C[j] = inv[j] * (j <= c - i);
59             D[j] = inv[j] * (j <= d - i);
60         }
61         NTT(A, limit, 1); NTT(B, limit, 1); NTT(C, limit, 1); NTT(D, limit, 1);
62         for(Rint j = 0;j < limit;j ++) A[j] = (LL) A[j] * B[j] % mod * C[j] % mod * D[j] % mod;
63         NTT(A, limit, -1);
64         int tmp = (LL) A[n - (i << 2)] * fac[n - 3 * i] % mod * inv[i] % mod;
65         if(i & 1) ans = (ans - tmp + mod) % mod;
66         else ans = (ans + tmp) % mod;
67     }
68     printf("%d", ans);
69 }
Luogu5339

 

Guess you like

Origin www.cnblogs.com/AThousandMoons/p/10991925.html