P8367 [LNOI2022] 盒

又有组合 trick 🥰。

首先这个操作转到前缀和上就是单点加减,最小代价容易得到:

\[\sum_{i=1}^n w_i |S_a(i)-S_b(i)| \]

其中 \(S_{a/b}\) 为前缀和。对所有可能的 \(b\) 计数,枚举每一位置上 \(b\) 的前缀和贡献。

\[\sum_{i=1}^n w_i\sum_{j=0}^S |S_a(i)-j|{j+i-1\choose i-1}{S-j+n-i-1\choose n-i-1} \]

组合数即将 \(j\) 分到前 \(i\) 个数,\(S-j\) 分到后 \(n-i\) 个数,容易插板法得出。于是有 \(O(nS)\) 的做法。

绝对值先讨论,钦定 \(j \le S_a(i)\)

则需要求出:

\[g(n,S,i,R)=\sum_{j=0}^R j{j+i-1\choose i-1}{S-j+n-i-1\choose n-i-1} \]

\[f(n,S,i,R)=\sum_{j=0}^R {j+i-1\choose i-1}{S-j+n-i-1\choose n-i-1} \]

\(i\) 位置上的贡献可以表示为:

\[res_i=w_i(i\cdot f(n,S,i,S_a(i))-g(n,S,i,S_a(i))) \]

\[g(n,S,i,R)=\sum_{j=0}^Rj{j+i-1\choose i-1}{S-j+n-i-1\choose n-i-1}\\ =\sum_{j=0}^Ri{j+i-1\choose i}{{S-j+n-i-1\choose n-i-1}} \\=\sum_{j=0}^{R-1}i{j+i\choose i}{{S-j+n-i-2\choose n-i-1}} \\= i\cdot f(n+1,S-1,i+1,R-1)\]

所以只考虑如何得到 \(f\)\(g\) 可同理维护。

而对于 \(i\) 递增,\(f\) 三、四维也递增,第三维上的增量为 \(O(n)\),第四维的增量为 \(O(S)\)。考虑能否以优秀复杂度实现三、四维上 \(+1\) 的更新。

\(R\gets R+1\) 的更新是容易的,按照上述式子直接计算即可。

于是考虑 \(i\gets i+1\)

对上式有个很牛的组合角度,对于 \(f(n,S,i,R)\) 的组合意义为有 \(S\) 个球,\(n\) 个盒子,其中前 \(i\) 个盒子中球的总数不超过 \(R\) 的方案数。考虑枚举第 \(R+1\) 个球在哪个盒子,得到:

\[f(n,S,i,R)=\sum_{j=i+1}^n {R+j-1\choose j-1}{S-R-1+n-j\choose n-j} \]

表示前 \(R\) 个球在前 \(j\) 个盒子里任取,后 \(S-R-1\) 个球在 \(j\)\(n\) 的盒子中取。

然后发现 \(i\) 个变化也表示出来了,所以三、四维的 \(+1\) 都能做到 \(O(1)\)。😱

对于 \(j>S_a(i)\) 的部分,以 \(f\) 为例,用全部情况的总贡献即所有球任意分入 \(n\) 个盒子的方案数 \({S+n-1\choose n-1}\) 再去掉 \(j\le S_a(i)\) 的部分即可。

比较坑的是当存在 \(S_a(i)=0\) 时,\(g(n,S,i,R)=i\cdot f(n+1,S-1,i+1,R-1)\)\(R-1\) 会出问题,简单特殊算一下即可。

Takanashi Rikka
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
#define fin(x) freopen(#x".in","r",stdin)
#define fout(x) freopen(#x".out","w",stdout)
#define fr(x) fin(x),fout(x);
#define Fr(x,y) fin(x),fout(y)
#define INPUT(_1,_2,FILE,...) FILE
#define IO(...) INPUT(__VA_ARGS__,Fr,fr)(__VA_ARGS__)
using namespace std;
using namespace __gnu_pbds;
#define mp make_pair
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define il inline
#define cfast ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define ll long long
#define ull unsigned long long
#define intz(x,y) memset((x),(y),sizeof((x)))
char *p1,*p2,buf[100000];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
#define tup(x) array<int,(x)>
inline ll read(){
    ll x=0,f=1;char ch=nc();
    while(ch<48||ch>57){if(ch=='-')f=-1;ch=nc();}
    while(ch>=48&&ch<=57)x=x*10+ch-48,ch=nc();
   	return x*f;
}
//void write(int x){cout<<x<<' ';}
//void write(pii x){cout<<"P("<<x.fi<<','<<x.se<<")\n";}
//void write(vector<auto>x){for(auto i:x)write(i);cout<<'\n';}
//void write(auto *a,int l,int r){for(int i=l;i<=r;i++)write(a[i]);cout<<'\n';}
inline ll lowbit(ll x){return x&-x;}
#define pcount(x) __builtin_popcount(x)
inline void cmx(auto &x,ll y){if(y>x)x=y;}
inline void cmn(auto &x,ll y){if(y<x)x=y;}
inline int max(vector<int>w){int res=-1e9;for(int i:w)cmx(res,i);return res;}
const int mod=998244353;
#define int ll
ll qp(ll x,int y=mod-2){ll res=1;for(;y;x=x*x%mod,y>>=1)if(y&1)res=res*x%mod;return res;}
const int N=3e6;
int fac[N+5],ifac[N+5];
il int C(int x,int y){return fac[x]*ifac[y]%mod*ifac[x-y]%mod;}
struct node{
	int n,S,i,R,res;
	il node(int x,int y){n=x,S=y,i=R=0,res=C(x+y-1,x-1);}
	il void add_i(){(res+=mod-C(R+i,i)*C(S-R+n-i-2,n-i-1)%mod)%=mod,++i;}
	il void add_r(){++R,(res+=C(R+i-1,i-1)*C(S-R+n-i-1,n-i-1)%mod)%=mod;}
};
int a[N],w[N];
inline void UesugiErii(){
	int n,S=0,ans=0;cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i],a[i]+=a[i-1];
	for(int i=1;i<n;i++)cin>>w[i];
	S=a[n];node x(n,S),y(n+1,S-1);
	for(int i=1,tmp=C(S+n-1,n-1),tg=C(S+n-1,n);i<n;i++){
		while(x.i<i)x.add_i();
		while(x.R<a[i])x.add_r();
		if(a[i])
			while(y.i<i+1)y.add_i();
			while(y.R<a[i]-1)y.add_r();
		(ans+=((i*tg%mod+mod-a[i]*tmp%mod)%mod+(a[i]?2*(a[i]*x.res%mod+mod-i%mod*y.res%mod)%mod:0))%mod*w[i]%mod)%=mod;
	}
	cout<<ans<<'\n';
}
signed main(){
	//IO();
	cfast;
	for(int i=fac[0]=1;i<=N;i++)fac[i]=fac[i-1]*i%mod;
	ifac[N]=qp(fac[N],mod-2);
	for(int i=N;i;i--)ifac[i-1]=ifac[i]*i%mod;
	int _=1;cin>>_;
	for(;_;_--)UesugiErii();
	return 0;
}
posted @ 2026-01-08 10:53  Uesugi1  阅读(5)  评论(2)    收藏  举报