题面
有 n n n 个不同的盒子排成一排。在初始状态下,第 i i i 个盒子放有 a i a_i ai 个货物,总货物数量为 S = ∑ i = 1 n a i S = \sum_{i = 1}^{n} a_i S=∑i=1nai。对于非负整数数组 ( b 1 , b 2 , … , b n ) (b_1, b_2, \ldots, b_n) (b1,b2,…,bn) 满足 ∑ i = 1 n b i = S \sum_{i = 1}^{n} b_i = S ∑i=1nbi=S,考察以下问题:
你想让第 i i i 个盒子中拥有恰好 b i b_i bi 个货物,为此你可以做如下操作若干次:对两个相邻的盒子,把其中一个盒子的恰好一个货物移动至另一个。对 i , i + 1 i, i + 1 i,i+1( 1 ≤ i < n 1 \le i < n 1≤i<n)号盒子做一次操作的代价为 w i w_i wi。注意:将 i \bm{i} i 号盒子的一个货物移动到 i + 1 \bm{i + 1} i+1 号盒子和将 i + 1 \bm{i + 1} i+1 号盒子的一个货物移动到 i \bm{i} i 号盒子的代价都是 w i \bm{w_i} wi。你需要保证在操作中不存在盒子中的货物数量是负数。
在以上问题下,定义从初始状态达到第 i i i 个盒子拥有恰好 b i b_i bi 个货物的状态的最小代价为 val ( b 1 , b 2 , … , b n ) \operatorname{val}(b_1, b_2, \ldots, b_n) val(b1,b2,…,bn),你需要求出对所有满足 ∑ i = 1 n b i = S \sum_{i = 1}^{n} b_i = S ∑i=1nbi=S 的非负整数数组 ( b 1 , b 2 , … , b n ) (b_1, b_2, \ldots, b_n) (b1,b2,…,bn), val ( b 1 , b 2 , … , b n ) \operatorname{val}(b_1, b_2, \ldots, b_n) val(b1,b2,…,bn) 的和。输出这个答案对 998244353 998244353 998244353 取模后的结果。
输入格式
本题有多组测试数据。输入的第一行包含一个正整数 T T T,表示测试数据组数。
对于每组数据,输入共三行。第一行一个正整数 n n n 表示盒子的个数,第二行 n n n 个正整数 a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,…,an 描述初始状态,第三行 n − 1 n - 1 n−1 个正整数 w 1 , w 2 , … , w n − 1 w_1, w_2, \ldots, w_{n - 1} w1,w2,…,wn−1 描述移动货物的代价。
输出格式
对于每组测试数据输出一行一个整数,表示对于所有满足 ∑ i = 1 n b i = S \sum_{i = 1}^{n} b_i = S ∑i=1nbi=S 的非负整数数组,达到目标的代价的最小值之和模 998244353 998244353 998244353 的结果。
样例 #1
样例输入 #1
2
2
2 3
65472
5
1 3 2 1 1
2 3 3 3
样例输出 #1
589248
8589
提示
【样例解释 #1】
对于第一组数据,一共有六种需要考虑的情形,它们的 b 1 b_1 b1 和 b 2 b_2 b2 构成的二元组 ( b 1 , b 2 ) (b_1, b_2) (b1,b2) 分别为 ( 0 , 5 ) , ( 1 , 4 ) , ( 2 , 3 ) , ( 3 , 2 ) , ( 4 , 1 ) , ( 5 , 0 ) (0, 5), (1, 4), (2, 3), (3, 2), (4, 1), (5, 0) (0,5),(1,4),(2,3),(3,2),(4,1),(5,0)。
对于第一种情形,需要至少 2 2 2 次移动,代价最小值为 65472 × 2 = 130944 65472 \times 2 = 130944 65472×2=130944。
对于第二种情形,需要至少 1 1 1 次移动,代价最小值为 65472 65472 65472。
对于第三种情形,不需要做任何操作,代价最小值为 0 0 0。
对于第四种情形,需要至少 1 1 1 次移动,代价最小值为 65472 65472 65472。
对于第五种情形,需要至少 2 2 2 次移动,代价最小值为 65472 × 2 = 130944 65472 \times 2 = 130944 65472×2=130944。
对于最后一种情形,需要至少 3 3 3 次移动,代价最小值为 65472 × 3 = 196416 65472 \times 3 = 196416 65472×3=196416。
因此,最小代价之和为 130944 + 65472 + 0 + 65472 + 130944 + 196416 = 589248 130944 + 65472 + 0 + 65472 + 130944 + 196416 = 589248 130944+65472+0+65472+130944+196416=589248。
【数据范围】
保证对于任何测试点的任何一组数据,有 2 ≤ n ≤ 5 × 10 5 2 \le n \le 5 \times {10}^5 2≤n≤5×105, 1 ≤ S ≤ 2 × 10 6 1 \le S \le 2 \times {10}^6 1≤S≤2×106, a i ≥ 0 a_i \ge 0 ai≥0, 0 ≤ w i < 998244353 0 \le w_i < 998244353 0≤wi<998244353。
测试点编号 | T ≤ T \le T≤ | n ≤ n \le n≤ | S ≤ S \le S≤ | 特殊性质 |
---|---|---|---|---|
1 ∼ 2 1 \sim 2 1∼2 | 1000 1000 1000 | 5 5 5 | 5 5 5 | A |
3 ∼ 4 3 \sim 4 3∼4 | 5 5 5 | 9 9 9 | 9 9 9 | 无 |
5 ∼ 8 5 \sim 8 5∼8 | 10 10 10 | 2000 2000 2000 | 2000 2000 2000 | 无 |
9 ∼ 12 9 \sim 12 9∼12 | 10 10 10 | 2000 2000 2000 | 2 × 10 5 2 \times {10}^5 2×105 | 无 |
13 ∼ 14 13 \sim 14 13∼14 | 2 2 2 | 2 × 10 5 2 \times {10}^5 2×105 | 2 × 10 5 2 \times {10}^5 2×105 | B |
15 ∼ 16 15 \sim 16 15∼16 | 2 2 2 | 2 × 10 5 2 \times {10}^5 2×105 | 2 × 10 5 2 \times {10}^5 2×105 | AC |
17 ∼ 18 17 \sim 18 17∼18 | 2 2 2 | 2 × 10 5 2 \times {10}^5 2×105 | 2 × 10 5 2 \times {10}^5 2×105 | 无 |
19 ∼ 20 19 \sim 20 19∼20 | 5 5 5 | 5 × 10 5 5 \times {10}^5 5×105 | 2 × 10 6 2 \times {10}^6 2×106 | 无 |
特殊性质 A:对于任意
1
≤
i
<
n
1 \le i < n
1≤i<n,
w
i
=
1
w_i = 1
wi=1。
特殊性质 B:对于任意
1
≤
i
<
n
−
20
1 \le i < n - 20
1≤i<n−20,
a
i
=
0
a_i = 0
ai=0。
特殊性质 C:最多只有
20
20
20 个
i
∈
[
1
,
n
]
i \in [1, n]
i∈[1,n] 满足
a
i
≠
0
a_i \ne 0
ai=0。
【提示】
本题有读入量较大的测试点,为了优化程序运行的时间,我们建议你采用较为快速的读入方式。
题解
【声明】本人是看过 OID 的讲解才做出来的
我们对于每个缝单独算贡献,在贪心的移动下,容易知道该缝的经过次数为左边 b b b 求和与 a a a 求和的差值。
令
a
i
a_i
ai 的前缀和为
A
i
A_i
Ai ,我们要求的就是
∑
k
=
1
n
−
1
w
k
∑
i
=
0
S
∣
A
k
−
i
∣
(
i
+
k
−
1
k
−
1
)
(
S
−
i
+
n
−
k
−
1
n
−
k
−
1
)
\sum_{k=1}^{n-1}w_k\sum_{i=0}^S|A_k-i|{i+k-1\choose k-1}{S-i+n-k-1\choose n-k-1}
k=1∑n−1wki=0∑S∣Ak−i∣(k−1i+k−1)(n−k−1S−i+n−k−1)
把绝对值拆开,变成条件,
∑
k
=
1
n
−
1
w
k
∑
i
=
0
A
k
(
A
k
−
i
)
(
i
+
k
−
1
k
−
1
)
(
S
−
i
+
n
−
k
−
1
n
−
k
−
1
)
\sum_{k=1}^{n-1}w_k\sum_{i=0}^{A_k}(A_k-i){i+k-1\choose k-1}{S-i+n-k-1\choose n-k-1}
k=1∑n−1wki=0∑Ak(Ak−i)(k−1i+k−1)(n−k−1S−i+n−k−1)
正反各求一遍就是答案。这时我们把
A
k
−
i
A_k-i
Ak−i 拆开来算贡献,已知
(
i
+
k
−
1
k
−
1
)
i
=
(
i
+
k
−
1
k
)
k
\bm{{i+k-1\choose k-1}i={i+k-1\choose k}k}
(k−1i+k−1)i=(ki+k−1)k
故上式为
∑
k
=
1
n
−
1
w
k
A
k
∑
i
=
0
A
k
(
i
+
k
−
1
k
−
1
)
(
S
−
i
+
n
−
k
−
1
n
−
k
−
1
)
−
∑
k
=
1
n
−
1
w
k
k
∑
i
=
0
A
k
(
i
+
k
−
1
k
)
(
S
−
i
+
n
−
k
−
1
n
−
k
−
1
)
\sum_{k=1}^{n-1}w_kA_k\sum_{i=0}^{A_k}{i+k-1\choose k-1}{S-i+n-k-1\choose n-k-1}\\ -\sum_{k=1}^{n-1}w_kk\sum_{i=0}^{A_k}{i+k-1\choose k}{S-i+n-k-1\choose n-k-1}
k=1∑n−1wkAki=0∑Ak(k−1i+k−1)(n−k−1S−i+n−k−1)−k=1∑n−1wkki=0∑Ak(ki+k−1)(n−k−1S−i+n−k−1)
两个结构相似,我们只考察上面一个,令
f
(
k
,
L
)
=
∑
i
=
0
L
−
k
(
i
+
k
−
1
k
−
1
)
(
S
−
i
+
n
−
k
−
1
n
−
k
−
1
)
=
∑
i
=
0
L
−
1
(
i
k
−
1
)
(
S
−
i
+
n
−
2
n
−
k
−
1
)
=
∑
i
=
0
L
−
1
(
i
k
−
1
)
(
1
1
)
(
S
−
i
+
n
−
2
n
−
k
−
1
)
f(k,L)=\sum_{i=0}^\bm{L~~-k}{i+k-1\choose k-1}{S-i+n-k-1\choose n-k-1}\\ =\sum_{i=0}^\bm{L-1}{i\choose k-1}{S-i+n-2\choose n-k-1}\\~\\ \bm{=\sum_{i=0}^{L-1}~~{i\choose k-1}{1\choose1}{S-i+n-2\choose n-k-1}}
f(k,L)=i=0∑L −k(k−1i+k−1)(n−k−1S−i+n−k−1)=i=0∑L−1(k−1i)(n−k−1S−i+n−2) =i=0∑L−1 (k−1i)(11)(n−k−1S−i+n−2)
转化成最后一个式子应该比较清晰了,我们考察它的组合意义,它其实就是 S + n − 1 S+n-1 S+n−1 个位置中选 n − 1 n-1 n−1 个,满足第 k \bm{k} k 个的位置 ≤ L \bm{\leq L} ≤L 的方案数。
f
(
k
,
L
)
f(k,L)
f(k,L) 是可以递推的,
f
(
k
+
1
,
L
)
=
f
(
k
,
L
)
−
(
L
k
)
(
S
+
n
−
1
−
L
n
−
1
−
k
)
f
(
k
,
L
+
1
)
=
f
(
k
,
L
)
+
(
L
k
−
1
)
(
S
+
n
−
2
−
L
n
−
1
−
k
)
f(k+1,L)=f(k,L)-{L\choose k}{S+n-1-L\choose n-1-k}\\ f(k,L+1)=f(k,L)+{L\choose k-1}{S+n-2-L\choose n-1-k}
f(k+1,L)=f(k,L)−(kL)(n−1−kS+n−1−L)f(k,L+1)=f(k,L)+(k−1L)(n−1−kS+n−2−L)
由于我们每次需要的是 f ( i , A i + k ) f(i,A_i+k) f(i,Ai+k) ,而 i i i 和 A i + k A_i+k Ai+k 都是递增的,所以均摊 O ( 1 ) O(1) O(1) 。
总时间复杂度 O ( n + S ) O(n+S) O(n+S) 。
CODE
#include<map>
#include<set>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<random>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<unordered_map>
//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast")
using namespace std;
#define MAXN 2500005
#define LL long long
#define ULL unsigned long long
#define ENDL putchar('\n')
#define DB double
#define lowbit(x) (-(x) & (x))
#define FI first
#define SE second
#define PR pair<int,int>
int xchar() {
static const int maxn = 1000000;
static char b[maxn];
static int pos = 0,len = 0;
if(pos == len) pos = 0,len = fread(b,1,maxn,stdin);
if(pos == len) return -1;
return b[pos ++];
}
// #define getchar() xchar()
LL read() {
LL f = 1,x = 0;int s = getchar();
while(s < '0' || s > '9') {if(s<0)return -1;if(s=='-')f=-f;s = getchar();}
while(s >= '0' && s <= '9') {x = (x<<1) + (x<<3) + (s^48);s = getchar();}
return f*x;
}
void putpos(LL x) {if(!x)return ;putpos(x/10);putchar((x%10)^48);}
void putnum(LL x) {
if(!x) {putchar('0');return ;}
if(x<0) putchar('-'),x = -x;
return putpos(x);
}
void AIput(LL x,int c) {putnum(x);putchar(c);}
const int MOD = 998244353;
int n,m,s,o,k;
inline int Abs(int x) {return x<0 ? -x:x;}
inline void MD(int &x) {if(x>=MOD)x-=MOD;}
int a[MAXN],w[MAXN];
int fac[MAXN],inv[MAXN],invf[MAXN];
inline int C(int n,int m) {
if(m < 0 || m > n) return 0;
return fac[n] *1ll* invf[n-m] % MOD * invf[m] % MOD;
}
int main() {
// freopen("box.in","r",stdin);
// freopen("box.out","w",stdout);
fac[0]=fac[1]=inv[0]=inv[1]=invf[0]=invf[1]=1;
for(int i = 2;i <= MAXN-5;i ++) {
fac[i] = fac[i-1] *1ll* i % MOD;
inv[i] = (MOD - inv[MOD%i]) *1ll* (MOD/i) % MOD;
invf[i] = invf[i-1] *1ll* inv[i] % MOD;
}
int T = read();
while(T --) {
n = read();
int S = 0;
for(int i = 1;i <= n;i ++) S += (a[i] = read());
for(int i = 1;i < n;i ++) w[i] = read();
int L = 0,ans = 0,L2 = 0;
int nm = C(S+n-1,n-1),lm = 0;
int nm2 = C(S+n-2,n-1),lm2 = 1;
for(int i = 1;i < n;i ++) {
L += a[i]+1; int p = i; L2 += a[i];
MD(nm += MOD- C(lm,p-1)*1ll*C(S+n-1-lm,n-p)%MOD);
MD(nm2 += MOD- C(lm2,p)*1ll*C(S+n-1-lm2,n-p)%MOD);
while(lm < L) {
lm ++;
MD(nm += C(lm-1,p-1)*1ll*C(S+n-1-lm,n-1-p)%MOD);
}
while(lm2 < L) {
lm2 ++;
MD(nm2 += C(lm2-1,p)*1ll*C(S+n-1-lm2,n-1-p)%MOD);
}
int as = (nm*1ll*w[i]%MOD*L2%MOD +MOD- nm2*1ll*w[i]%MOD*p%MOD)%MOD;
MD(ans += as);
}
L = 0; nm = C(S+n-1,n-1); lm = 0; L2 = 0;
nm2 = C(S+n-2,n-1); lm2 = 1;
for(int i = n-1;i > 0;i --) {
L += a[i+1]+1; int p = n-i; L2 += a[i+1];
MD(nm += MOD- C(lm,p-1)*1ll*C(S+n-1-lm,n-p)%MOD);
MD(nm2 += MOD- C(lm2,p)*1ll*C(S+n-1-lm2,n-p)%MOD);
while(lm < L) {
lm ++;
MD(nm += C(lm-1,p-1)*1ll*C(S+n-1-lm,n-1-p)%MOD);
}
while(lm2 < L) {
lm2 ++;
MD(nm2 += C(lm2-1,p)*1ll*C(S+n-1-lm2,n-1-p)%MOD);
}
MD(ans += nm*1ll*w[i]%MOD*L2%MOD);
MD(ans += MOD- nm2*1ll*w[i]%MOD*p%MOD);
}
AIput(ans,'\n');
}
return 0;
}