【The 13th Chinese Northeast Collegiate Programming Contest】I. Temperature Survey

题目描述

[题目链接](https://codeforces.com/gym/102220/problem/I)

给定长度为 $n$ 的 $a$ 序列,保证 $a_n \le n$,求有多少个长度为 $n$ 的 $b$ 序列,满足 $b_{i-1} \le b_i \le a_i$,答案模 $998244353$

数据范围:$1 \le n \le 2 \times 10^5$

题解

显然 $a$ 序列也是满足 $a_{i-1} \le a_i$,否则在 $a_{i-1} > a_i$ 的时候把 $a_{i-1}$ 变为 $a_i$

考虑模拟题意,设 $f_{i,j}$ 表示考虑完 $b_1,b_2,\cdots,b_i$,其中 $b_i=j$ 的方案数

显然有 $f_{i,j}=\sum_{k=0}^{j} f_{i-1,k}=f_{i-1,j}+f_{i,j-1}$

换句话说,相当于一开始有 $b_i=[i=1]$,依次做 $n$ 次前缀和,每次把 $b$ 的前 $a_i$ 个元素做一次前缀和(然而这个转化是做不了的似乎)

从另一个角度看,相当于从 $(n,j)$ 走到 $(1,1)$ 的方案数,其中 $1 \le j \le a_n$

然而这个还是太麻烦,不如再加上 $a_{n+1}=n+1$,这样就是 $(n+1,n+1)$ 走到 $(1,1)$ 的方案数了

为了方便起见,把这个 $a$ 序列翻转一下,也就是从 $(1,n+1)$ 走到 $(n+1,1)$ 的方案数

考虑分治,对于区间 $[l,r]$,就提取出来一个高度为 $a_{mid}$ 的极大矩形,然后递归做即可

考虑实现函数 $rect(l,r,bot,top)$,表示解决矩形 $[l,r] \times [bot,top]$ 的答案(即解决右边界和下边界)

设 $n=height,m=width$,且上边界的答案为 $a$,左边界的答案为 $b$,那么一共就如下几种情况:

如果是上边界到下边界,设生成函数为 $P(x)$,则:

$$
\begin{aligned}
P(x)=\sum_{i=0}^{m-1}\sum_{j=0}^{i} a_j {i-j+n-1 \choose n-1} x^i
\end{aligned}
$$

如果是左边界到右边界,设生成函数为 $Q(x)$,则:

$$
\begin{aligned}
Q(x)=\sum_{i=0}^{n-1}\sum_{j=0}^{i} b_j {i-j+m-1 \choose m-1} x^i
\end{aligned}
$$

如果是左边界到下边界,考虑到 $i-j$ 可能会小于 $0$,不妨先把它平移一下,设原先的生成函数为 $B(x)$,则平移后为 $x^{n-1}B(x)$,即:

$$
\begin{aligned}
&B(x)=\sum_{i=0}^{m-1}\sum_{j=0}^{n-1}b_j {i+n-1-j \choose i} x^i \\
\Rightarrow
&x^{n-1}B(x)=\sum_{i=n-1}^{n+m-2}\sum_{j=0}^{n-1} b_j {i-j \choose i-n+1} x^i \\
\Rightarrow
&x^{n-1}B(x)=\sum_{i=n-1}^{n+m-2}\sum_{j=0}^{n-1} b_j {i-j \choose i-n+1} x^i \\
\Rightarrow
&x^{x-1}B(x)=\sum_{i=n-1}^{n+m-2}\sum_{j=0}^{n-1}b_j \frac{(i-j)!}{(i-n+1)!(n-1-j)!} x^i \\
\Rightarrow
&x^{x-1}B(x)=\sum_{i=n-1}^{n+m-2} \frac{x^i}{(i-n+1)!} \sum_{j=0}^{i} \frac{b_j}{(n-1-j)!} (i-j)!
\end{aligned}
$$

如果是上边界到右边界,依然考虑 $i-j$ 可能会小于 $0$,因此把它平移一下,设原先的生成函数为 $A(x)$,平移后就是 $x^{m-1}A(x)$,即:

$$
\begin{aligned}
&A(x)=\sum_{i=0}^{n-1}\sum_{j=0}^{m-1} a_j {i+m-1-j \choose i} x^i \\
\Rightarrow
&x^{m-1}A(x)=\sum_{i=m-1}^{n+m-2}\sum_{j=0}^{m-1} a_j {i-j \choose i-m+1} x^i \\
\Rightarrow
&x^{m-1}A(x)=\sum_{i=m-1}^{n+m-2}\sum_{j=0}^{m-1}a_j \frac{(i-j)!}{(i-m+1)!(m-1-j)!}x^i \\
\Rightarrow
&x^{m-1}A(x)=\sum_{i=m-1}^{n+m-2} \frac{x^i}{(i-m+1)!} \sum_{j=0}^{m-1} \frac{a_j}{(m-1-j)!} (i-j)!
\end{aligned}
$$

这些部分都可以多项式乘法做完,于是这一部分的时间复杂度是 $O((n+m) \log (n+m))$

考虑到每次分治过程中,同一层的矩形互不相交,于是 $n+m$ 之和是 $a$ 的长度级别的,因此同一层的时间复杂度为 $O(|a| \log |a|)$,由于一共有 $O(\log |a|)$ 层,因此总的时间复杂度为 $O(|a| \log^2 |a|)$

代码

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 
  5 #pragma GCC target ("avx2")
  6 
  7 #define __AVX__ 1
  8 #define __AVX2__ 1
  9 #define __SSE__ 1
 10 #define __SSE2__ 1
 11 #define __SSE2_MATH__ 1
 12 #define __SSE3__ 1
 13 #define __SSE4_1__ 1
 14 #define __SSE4_2__ 1
 15 #define __SSE_MATH__ 1
 16 #define __SSSE3__ 1
 17 
 18 
 19 #include <immintrin.h>
 20 
 21 #include "bits/stdc++.h"
 22 
 23 using namespace std;
 24 
 25 typedef unsigned char U8;
 26 typedef int I32;
 27 typedef unsigned int U32;
 28 typedef long long I64;
 29 typedef unsigned long long U64;
 30 
 31 const int P=998244353;
 32 const int inv2=(P+1)>>1;
 33 const int G=3;
 34 const int GInv=332748118;
 35 const int MaxExp=25;
 36 const int MAXN=1048576<<2;
 37 const int MAXK=500005;
 38 const int BmM=288737297;
 39 const int BmW=29;
 40 
 41 #define maxl (524300 * 2)
 42 typedef long long ll;
 43 using namespace std;
 44 
 45 
 46 int r[maxl],len,l;
 47 U32 A[maxl],B[maxl];
 48 const ll p=998244353,_g[2]={3,332748118};
 49 ll pw(ll a,ll b){
 50     // printf("a=%lld b=%lld\n",a,b);
 51     ll ret=1;
 52     while(b){
 53         if(b&1)
 54             ret=ret*a%p;
 55         a=a*a%p,b>>=1;
 56     }
 57     return ret;
 58 }
 59 void modify(int x){
 60     for(len=1,l=0;len<=x;len<<=1,l++);
 61     for(int i=0;i<len;i++)
 62         r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
 63 }
 64 
 65 namespace NTT{
 66 
 67 
 68     U32 GcdEx(U32 A, U32 B, I32& x, I32& y) {
 69         if (!B) {
 70             x = 1;
 71             y = 0;
 72             return A;
 73         }
 74         U32 d = GcdEx(B, A % B, y, x);
 75         y -= x * (I32) (A / B);
 76         return d;
 77     }
 78 
 79     inline U32 MNorm(I32 V) {
 80         V = V % P;
 81         return (U32) (V < 0 ? V + P : V);
 82     }
 83 
 84     inline U32 MAdd(U32 A, U32 B) {
 85         U32 res = A + B;
 86         return res < P ? res : res - P;
 87     }
 88 
 89     inline U32 MSub(U32 A, U32 B) {
 90         U32 res = A - B;
 91         return A < B ? res + P : res;
 92     }
 93 
 94     inline U32 MMul(U32 A, U32 B) {
 95         return (U32) ((U64) A * B % P);
 96     }
 97 
 98     inline U32 MPow(U32 A, U32 B) {
 99         U32 res = 1;
100         while (B) {
101             if (B & 1)
102                 res = MMul(res, A);
103             A = MMul(A, A);
104             B >>= 1;
105         }
106         return res;
107     }
108 
109     inline U32 MInv(U32 N) {
110         I32 x, y;
111         GcdEx(N, P, x, y);
112         x %= P;
113         return (U32) (x < 0 ? x + P : x);
114     }
115 
116     inline __m256i VLod(const U32* __restrict__ A) {
117         return _mm256_load_si256((const __m256i*) A);
118     }
119 
120     inline void VSto(U32* __restrict__ A, __m256i v) {
121         _mm256_store_si256((__m256i*) A, v);
122     }
123 
124     inline __m256i VEx0(__m256i v) {
125         const __m256i vm0 = _mm256_set_epi64x(
126             0x111111111b1a1918, 0x1111111113121110,
127             0x111111110b0a0908, 0x1111111103020100
128         );
129         return _mm256_shuffle_epi8(v, vm0);
130     }
131 
132     inline __m256i VEx1(__m256i v) {
133         const __m256i vm1 = _mm256_set_epi64x(
134             0x111111111f1e1d1c, 0x1111111117161514,
135             0x111111110f0e0d0c, 0x1111111107060504
136         );
137         return _mm256_shuffle_epi8(v, vm1);
138     }
139 
140     inline __m256i VIntlv(__m256i v0, __m256i v1) {
141         return _mm256_blend_epi32(v0, _mm256_shuffle_epi32(v1, 0xb1), 0xaa);
142     }
143 
144     inline __m256i VAdd(__m256i va, __m256i vb) {
145         const __m256i vm32 = _mm256_set1_epi32(P);
146         __m256i vra = _mm256_add_epi32(va, vb);
147         __m256i vrb = _mm256_sub_epi32(vra, vm32);
148         return _mm256_min_epu32(vra, vrb);
149     }
150 
151     inline __m256i VSub(__m256i va, __m256i vb) {
152         const __m256i vm32 = _mm256_set1_epi32(P);
153         __m256i vra = _mm256_sub_epi32(va, vb);
154         __m256i vrb = _mm256_add_epi32(vra, vm32);
155         return _mm256_min_epu32(vra, vrb);
156     }
157 
158     inline __m256i VMul(__m256i va0, __m256i va1, __m256i vb0, __m256i vb1) {
159         const __m256i vm32 = _mm256_set1_epi32(P);
160         const __m256i vm64 = _mm256_set1_epi64x(P);
161         const __m256i vbmm = _mm256_set1_epi64x(BmM);
162         __m256i vmul0 = _mm256_mul_epi32(va0, vb0);
163         __m256i vmul1 = _mm256_mul_epi32(va1, vb1);
164         __m256i vlow = VIntlv(vmul0, vmul1);
165         __m256i vquo0 = _mm256_srli_epi64(_mm256_mul_epi32(_mm256_srli_epi64(vmul0, 29), vbmm), BmW);
166         __m256i vquo1 = _mm256_srli_epi64(_mm256_mul_epi32(_mm256_srli_epi64(vmul1, 29), vbmm), BmW);
167         __m256i vval0 = _mm256_mul_epi32(vquo0, vm64);
168         __m256i vval1 = _mm256_mul_epi32(vquo1, vm64);
169         __m256i vval = VIntlv(vval0, vval1);
170         __m256i vra = _mm256_sub_epi32(vlow, vval);
171         __m256i vrb = _mm256_add_epi32(vra, vm32);
172         __m256i vrc = _mm256_sub_epi32(vra, vm32);
173         __m256i vmin = _mm256_min_epu32(vra, vrb);
174         return _mm256_min_epu32(vmin, vrc);
175     }
176 
177     inline __m256i VMul(__m256i va, __m256i vb0, __m256i vb1) {
178         return VMul(VEx0(va), VEx1(va), vb0, vb1);
179     }
180 
181     inline __m256i VMul(__m256i va, __m256i vb) {
182         return VMul(va, VEx0(vb), VEx1(vb));
183     }
184 
185     inline void VMul(U32* __restrict__ A, U32 Len, U32 W) {
186         if (Len < 8) {
187             for (U32 i = 0; i < Len; ++i)
188                 A[i] = MMul(A[i], W);
189             return;
190         }
191         __m256i vw = _mm256_set1_epi64x(W);
192         for (U32 i = 0; i < Len; i += 8)
193             VSto(A + i, VMul(VLod(A + i), vw, vw));
194     }
195 
196     inline void VMul(U32* __restrict__ A, const U32* __restrict__ B, U32 Len) {
197         if (Len < 8) {
198             for (U32 i = 0; i < Len; ++i)
199                 A[i] = MMul(A[i], B[i]);
200             return;
201         }
202         for (U32 i = 0; i < Len; i += 8)
203             VSto(A + i, VMul(VLod(A + i), VLod(B + i)));
204     }
205 
206     inline void VSqr(U32* __restrict__ A, U32 Len) {
207         if (Len < 8) {
208             for (U32 i = 0; i < Len; ++i)
209                 A[i] = MMul(A[i], A[i]);
210             return;
211         }
212         for (U32 i = 0; i < Len; i += 8) {
213             __m256i va = VLod(A + i);
214             __m256i v0 = VEx0(va);
215             __m256i v1 = VEx1(va);
216             VSto(A + i, VMul(v0, v1, v0, v1));
217         }
218     }
219 
220     U32 WbFwd[MaxExp + 1];
221     U32 WbInv[MaxExp + 1];
222     U32 LenInv[MaxExp + 1];
223 
224     inline void NttInitAll(int Max) {
225         for (int Exp = 0; Exp <= Max; ++Exp) {
226             WbFwd[Exp] = MPow(G, (P - 1) >> Exp);
227             WbInv[Exp] = MPow(GInv, (P - 1) >> Exp);
228             LenInv[Exp] = MInv(1u << Exp);
229         }
230     }
231 
232     inline void NttImpl1(U32* __restrict__ A, U32 Len) {
233         for (U32 j = 0; j < Len; j += 2) {
234             U32 a0 = MAdd(A[j + 0], A[j + 1]);
235             U32 b0 = MSub(A[j + 0], A[j + 1]);
236             A[j + 0] = a0;
237             A[j + 1] = b0;
238         }
239     }
240 
241     inline void NttFwd2(U32* __restrict__ A, U32 Len, U32 Wn) {
242         for (U32 j = 0; j < Len; j += 4) {
243             U32 a0 = MAdd(A[j + 0], A[j + 2]);
244             U32 a1 = MAdd(A[j + 1], A[j + 3]);
245             U32 b0 = MSub(A[j + 0], A[j + 2]);
246             U32 b1 = MSub(A[j + 1], A[j + 3]);
247             A[j + 0] = a0;
248             A[j + 1] = a1;
249             A[j + 2] = b0;
250             A[j + 3] = MMul(b1, Wn);
251         }
252     }
253 
254     inline void NttFwd3(U32* __restrict__ A, U32 Len, U32 Wn) {
255         U32 W2 = MMul(Wn, Wn);
256         U32 W3 = MMul(W2, Wn);
257         const __m128i vm32 = _mm_set1_epi32(P);
258         for (U32 j = 0; j < Len; j += 8) {
259             __m128i va = _mm_load_si128((const __m128i*) (A + j));
260             __m128i vb = _mm_load_si128((const __m128i*) (A + j + 4));
261             __m128i vc = _mm_add_epi32(va, vb);
262             __m128i vd = _mm_sub_epi32(va, vb);
263             __m128i ve = _mm_sub_epi32(vc, _mm_andnot_si128(_mm_cmpgt_epi32(vm32, vc), vm32));
264             __m128i vf = _mm_add_epi32(vd, _mm_and_si128(_mm_cmpgt_epi32(vb, va), vm32));
265             _mm_store_si128((__m128i*) (A + j), ve);
266             _mm_store_si128((__m128i*) (A + j + 4), vf);
267             A[j + 5] = MMul(Wn, A[j + 5]);
268             A[j + 6] = MMul(W2, A[j + 6]);
269             A[j + 7] = MMul(W3, A[j + 7]);
270         }
271     }
272 
273     inline void NttFwd(U32* __restrict__ A, int Exp) {
274         U32 Len = 1u << Exp;
275         U32 Wn = WbFwd[Exp];
276         for (int i = Exp - 1; i >= 3; --i) {
277             U32 ChkSiz = 1u << i;
278             U32 tw2 = MMul(Wn, Wn);
279             U32 tw3 = MMul(tw2, Wn);
280             U32 tw4 = MMul(tw3, Wn);
281             U32 tw5 = MMul(tw4, Wn);
282             U32 tw6 = MMul(tw5, Wn);
283             U32 tw7 = MMul(tw6, Wn);
284             U32 twn = MMul(tw7, Wn);
285             __m256i vw32 = _mm256_set_epi32(tw7, tw6, tw5, tw4, tw3, tw2, Wn, 1);
286             __m256i vwn = _mm256_set1_epi64x(twn);
287             for (U32 j = 0; j < Len; j += 2u << i) {
288                 U32* A_ = A + j;
289                 U32* B_ = A_ + ChkSiz;
290                 __m256i vw = vw32;
291                 for (U32 k = 0; k < ChkSiz; k += 8) {
292                     __m256i va = VLod(A_ + k);
293                     __m256i vb = VLod(B_ + k);
294                     __m256i vw0 = VEx0(vw);
295                     __m256i vw1 = VEx1(vw);
296                     __m256i vc = VAdd(va, vb);
297                     __m256i vd = VSub(va, vb);
298                     VSto(A_ + k, vc);
299                     VSto(B_ + k, VMul(vd, vw0, vw1));
300                     vw = VMul(vw0, vw1, vwn, vwn);
301                 }
302             }
303             Wn = MMul(Wn, Wn);
304         }
305         if (Exp >= 3) {
306             NttFwd3(A, Len, Wn);
307             Wn = MMul(Wn, Wn);
308         }
309         if (Exp >= 2)
310             NttFwd2(A, Len, Wn);
311         if (Exp)
312             NttImpl1(A, Len);
313     }
314 
315     inline void NttInv2(U32* __restrict__ A, U32 Len, U32 Wn) {
316         for (U32 j = 0; j < Len; j += 4) {
317             U32 a0 = A[j + 0];
318             U32 a1 = A[j + 1];
319             U32 b0 = A[j + 2];
320             U32 b1 = MMul(A[j + 3], Wn);
321             A[j + 0] = MAdd(a0, b0);
322             A[j + 1] = MAdd(a1, b1);
323             A[j + 2] = MSub(a0, b0);
324             A[j + 3] = MSub(a1, b1);
325         }
326     }
327 
328     inline void NttInv3(U32* __restrict__ A, U32 Len, U32 Wn) {
329         U32 W2 = MMul(Wn, Wn);
330         U32 W3 = MMul(W2, Wn);
331         const __m128i vm32 = _mm_set1_epi32(P);
332         for (U32 j = 0; j < Len; j += 8) {
333             A[j + 5] = MMul(Wn, A[j + 5]);
334             A[j + 6] = MMul(W2, A[j + 6]);
335             A[j + 7] = MMul(W3, A[j + 7]);
336             __m128i va = _mm_load_si128((const __m128i*) (A + j));
337             __m128i vb = _mm_load_si128((const __m128i*) (A + j + 4));
338             __m128i vc = _mm_add_epi32(va, vb);
339             __m128i vd = _mm_sub_epi32(va, vb);
340             __m128i ve = _mm_sub_epi32(vc, _mm_andnot_si128(_mm_cmpgt_epi32(vm32, vc), vm32));
341             __m128i vf = _mm_add_epi32(vd, _mm_and_si128(_mm_cmpgt_epi32(vb, va),vm32));
342             _mm_store_si128((__m128i*) (A + j), ve);
343             _mm_store_si128((__m128i*) (A + j + 4), vf);
344         }
345     }
346 
347     inline void NttInv(U32* __restrict__ A, int Exp) {
348         if (!Exp)
349             return;
350         U32 Len = 1u << Exp;
351         NttImpl1(A, Len);
352         if (Exp == 1) {
353             VMul(A, Len, LenInv[1]);
354             return;
355         }
356         U32 Ws[MaxExp];
357         Ws[0] = WbInv[Exp];
358         for (int i = 1; i < Exp; ++i)
359             Ws[i] = MMul(Ws[i - 1], Ws[i - 1]);
360         NttInv2(A, Len, Ws[Exp - 2]);
361         if (Exp == 2) {
362             VMul(A, Len, LenInv[2]);
363             return;
364         }
365         NttInv3(A, Len, Ws[Exp - 3]);
366         if (Exp == 3) {
367             VMul(A, Len, LenInv[3]);
368             return;
369         }
370         for (int i = 3; i < Exp; ++i) {
371             U32 ChkSiz = 1u << i;
372             U32 Wn = Ws[Exp - 1 - i];
373             U32 tw2 = MMul(Wn, Wn);
374             U32 tw3 = MMul(tw2, Wn);
375             U32 tw4 = MMul(tw3, Wn);
376             U32 tw5 = MMul(tw4, Wn);
377             U32 tw6 = MMul(tw5, Wn);
378             U32 tw7 = MMul(tw6, Wn);
379             U32 twn = MMul(tw7, Wn);
380             __m256i vw32 = _mm256_set_epi32(tw7, tw6, tw5, tw4, tw3, tw2, Wn, 1);
381             __m256i vwn = _mm256_set1_epi64x(twn);
382             for (U32 j = 0; j < Len; j += 2u << i) {
383                 U32* A_ = A + j;
384                 U32* B_ = A_ + ChkSiz;
385                 __m256i vw = vw32;
386                 for (U32 k = 0; k < ChkSiz; k += 8) {
387                     __m256i vw0 = VEx0(vw);
388                     __m256i vw1 = VEx1(vw);
389                     __m256i vb = VMul(VLod(B_ + k), vw0, vw1);
390                     vw = VMul(vw0, vw1, vwn, vwn);
391                     __m256i va = VLod(A_ + k);
392                     __m256i vc = VAdd(va, vb);
393                     __m256i vd = VSub(va, vb);
394                     VSto(A_ + k, vc);
395                     VSto(B_ + k, vd);
396                 }
397             }
398         }
399         VMul(A, Len, LenInv[Exp]);
400     }
401 
402     inline int Log2Ceil(U32 N) {
403         static const U8 Table[32] = {
404             0,  9,  1,  10, 13, 21, 2,  29,
405             11, 14, 16, 18, 22, 25, 3,  30,
406             8,  12, 20, 28, 15, 17, 24, 7,
407             19, 27, 23, 6,  26, 5,  4,  31,
408         };
409         N = (N << 1) - 1;
410         N |= N >> 1;
411         N |= N >> 2;
412         N |= N >> 4;
413         N |= N >> 8;
414         N |= N >> 16;
415         return (int) Table[(N * 0x07c4acddu) >> 27];
416     }
417 }
418 
419 using namespace NTT;
420 
421 const int mod = 998244353, N = 5e6 + 10;
422 
423 int n, a[N];
424 
425 ll getinv(ll n) {
426     return pw(n, mod - 2);
427 }
428 
429 ll fac[N], invfac[N], inv[N];
430 void init(int n) {
431     fac[0] = invfac[0] = inv[0] = 1;
432     for(int i = 1 ; i <= n ; ++ i) {
433         fac[i] = fac[i - 1] * i % mod;
434         inv[i] = getinv(i);
435     }
436     invfac[n] = pw(fac[n], mod - 2);
437     for(int i = n - 1 ; i ; -- i) {
438         invfac[i] = invfac[i + 1] * (i + 1) % mod;
439     }
440 }
441 
442 void upd(int &x, int y) {
443     x = ((ll) x + y) % mod;
444 }
445 
446 void mul(vector<int> &a, vector<int> &b) {
447     // 计算这两个序列的卷积
448     vector<int> c(a.size() + b.size() - 1);
449     // for(int i = 0 ; i < a.size() ; ++ i) {
450     //     for(int j = 0 ; j < b.size() ; ++ j) {
451     //         upd(c[i + j], (ll) a[i] * b[j] % mod);
452     //     }
453     // }
454     // a = c; return ;
455 
456     int len = 1; while(len <= c.size() * 2) len <<= 1;
457     int lg2 = Log2Ceil(len);
458 
459     // printf("%d, %d %d, %d\n", len, a.size(), b.size(), c.size());
460 
461     for(int i = 0 ; i < len ; ++ i) {
462         A[i] = B[i] = 0;
463     }
464     for(int i = 0 ; i < a.size() ; ++ i) {
465         A[i] = a[i];
466     }
467     for(int i = 0 ; i < b.size() ; ++ i) {
468         B[i] = b[i];
469     }
470     NttFwd(A, lg2), NttFwd(B, lg2);
471     for(int i = 0 ; i < len ; ++ i) {
472         A[i] = (ll) A[i] * B[i] % mod;
473     }
474     NttInv(A, lg2);
475     for(int i = 0 ; i < c.size() ; ++ i) {
476         c[i] = A[i];
477     }
478     a = c;
479 }
480 ll C(int n, int m) {
481     return n < m || m < 0 ? 0 : fac[n] * invfac[m] % mod * invfac[n - m] % mod;
482 }
483 
484 map<int, int> dp[N];
485 
486 void sol_rect(int l, int r, int bot, int top) {
487     // 左右边界,下边界,上边界
488 
489     // printf("处理: [%d, %d] - [%d, %d]\n", l, r, bot, top);
490 
491     if(l == 1 && r == 1 && top == n + 1) {
492         // puts("VIS");
493         // 就是这玩意,起始位置,左上角
494         for(int i = bot ; i <= top ; ++ i) {
495             dp[l][i] = 1;
496             // printf("dp[%d][%d] = %d\n", l, i, dp[l][i]);
497         }
498         return ;
499     }
500 
501     int width = r - l + 1, height = top - bot + 1;
502 
503     vector<int> bottom(width), right(height); // 底下和右侧的答案
504     vector<int> a(width); // 上面的
505     vector<int> b(height); // 左面的
506     for(int i = 0 ; i < width ; ++ i) {
507         a[i] = dp[l + i][top + 1];
508     }
509     for(int i = 0 ; i < height ; ++ i) {
510         b[i] = dp[l - 1][top - i];
511     }
512 
513     // printf("a: ");
514     // for(int x: a) printf("%d ", x); puts("");
515     // printf("b: ");
516     // for(int x: b) printf("%d ", x); puts("");
517 
518     {
519         // left -> bottom
520         // for(int i = 0 ; i < width ; ++ i) {
521         //     for(int j = 0 ; j < height ; ++ j) {
522         //         upd(bottom[i], (ll) b[j] * C(i + height - 1 - j, i) % mod);
523         //     }
524         // }
525 
526         vector<int> x(height), y(width + height - 1);
527         for(int i = 0 ; i < height ; ++ i) {
528             x[i] = (ll) b[i] * invfac[height - 1 - i] % mod;
529         }
530         for(int i = 0 ; i < width + height - 1 ; ++ i) {
531             y[i] = fac[i];
532         }
533         mul(x, y);
534         for(int i = 0 ; i < width ; ++ i) {
535             upd(bottom[i], (ll) x[height - 1 + i] * invfac[i] % mod);
536         }
537     }
538 
539     {
540         // top -> bottom
541         // for(int i = 0 ; i < width ; ++ i) {
542         //     for(int j = 0 ; j <= i ; ++ j) {
543         //         upd(bottom[i], (ll) a[j] * C(i - j + height - 1, height - 1) % mod);
544         //     }
545         // }
546         vector<int> x(width), y(width);
547         for(int i = 0 ; i < width ; ++ i) {
548             x[i] = a[i];
549             y[i] = C(i + height - 1, height - 1);
550         }
551         mul(x, y);
552         for(int i = 0 ; i < width ; ++ i) {
553             upd(bottom[i], x[i]);
554         }
555     }
556 
557     {
558         // top -> right
559         // for(int i = 0 ; i < height ; ++ i) {
560         //     for(int j = 0 ; j < width ; ++ j) {
561         //         upd(right[i], (ll) a[j] * C(i + width - 1 - j, i) % mod);
562         //     }
563         // }
564         vector<int> x(width), y(width + height - 1);
565         for(int i = 0 ; i < width ; ++ i) {
566             x[i] = (ll) a[i] * invfac[width - 1 - i] % mod;
567         }
568         for(int i = 0 ; i < width + height - 1 ; ++ i) {
569             y[i] = fac[i];
570         }
571         mul(x, y);
572         for(int i = 0 ; i < height ; ++ i) {
573             upd(right[i], (ll) x[width - 1 + i] * invfac[i] % mod);
574         }
575     }
576 
577     {
578         // left -> right
579         // for(int i = 0 ; i < height ; ++ i) {
580         //     for(int j = 0 ; j <= i ; ++ j) {
581         //         upd(right[i], (ll) b[j] * C(i - j + width - 1, width - 1) % mod);
582         //     }
583         // }
584         vector<int> x(height), y(height);
585         for(int i = 0 ; i < height ; ++ i) {
586             x[i] = b[i];
587             y[i] = C(i + width - 1, width - 1);
588         }
589         mul(x, y);
590         for(int i = 0 ; i < height ; ++ i) {
591             upd(right[i], x[i]);
592         }
593     }
594 
595     // printf("right: ");
596     // for(int x: right) printf("%d ", x); puts("");
597     // printf("bottom: ");
598     // for(int x: bottom) printf("%d ", x); puts("");
599 
600     for(int i = l ; i <= r ; ++ i) {
601         upd(dp[i][bot], bottom[i - l]);
602         // printf("dp_1[%d][%d] = %d\n", i, bot, dp[i][bot]);
603     }
604     for(int i = top ; i >= bot ; -- i) {
605 
606         // 由于右下角会被算两次,所以这里先鸽一次
607         if(i == bot) continue;
608 
609         upd(dp[r][i], right[top - i]);
610         // printf("dp_2[%d][%d] = %d\n", r, i, dp[r][i]);
611     }
612 }
613 
614 void sol(int l, int r, int bot) {
615     // 左右边界,底边的高度
616     if(l > r) {
617         return ;
618     }
619     int mid = (l + r) >> 1;
620     int x = mid, y = mid;
621     while(x - 1 >= l && a[x - 1] == a[mid]) -- x;
622     while(y + 1 <= r && a[y + 1] == a[mid]) ++ y;
623     sol(l, x - 1, a[mid] + 1);
624 
625     // printf("mid = %d\n", mid);
626     // printf("x = %d, y = %d\n", x, y);
627     sol_rect(l, y, bot, a[mid]);
628     sol(y + 1, r, bot);
629 }
630 
631 int main() {
632     NttInitAll(22);
633     init(N - 1);
634     int t; scanf("%d", &t);
635     while(t --) {
636         scanf("%d", &n);
637         for(int i = 1 ; i <= n ; ++ i) {
638             scanf("%d", &a[i]);
639         }
640         a[n + 1] = n + 1;
641         reverse(a + 1, a + 1 + n + 1);
642         for(int i = 0 ; i <= n + 1 ; ++ i) {
643             dp[i].clear();
644         }
645 
646         // for(int i = 1 ; i <= n + 1 ; ++ i) {
647         //     printf("%d ", a[i]);
648         // } puts("");
649 
650         sol(1, n + 1, 1);
651         printf("%d\n", ((ll) dp[n + 1][1] % mod + mod) % mod);
652     }
653 }
【The 13th Chinese Northeast Collegiate Programming Contest】I. Temperature Survey

 

posted @ 2019-06-14 08:40  KingSann  阅读(420)  评论(0编辑  收藏  举报