一、题目描述:
给定一个长度为 $n$ 的序列 $B$,和一个长度为 $n-1$ 的序列 $C$。
保证 $b_i>=0$。令$S=\sum_{i=1}^n b_i$。
一个长度为 $n$ 的且 $\sum_{i=1}^n a_i=S$ 序列 $A$ 的代价按照如下计算:
你可以若干次任意选择一个 $i\in [1,n-1]$,然后选择下面两项之一:
1、$a_i++,a_{i+1}--$
2、$a_i--,a_{i+1}++$
此操作的代价为 $c_i$
$A$ 的代价即为把 $A$ 变成 $B$ 的最小代价。
求出所有长度为 $n,a_i>=0$ 且 $\sum_{i=1}^na_i=S$ 的 $A$ 的代价和。答案对 $998244353$ 取模。
数据范围:$1\le n\le 5\times 10^5,0\le S\le 2*10^6$。
二、解题思路:
令 $Sa_i=\sum_{k=1}^i a_k,Sb_i=\sum_{k=1}^i b_k$,于是可以比较简单地列出式子:
$ans=\sum_{i=1}^{n-1}\sum_{Sa_i=0}^{V}\left|Sa_i-Sb_i\right|\times {Sa_i+i-1\choose i-1}{V+n-i-Sa_i-1\choose n-i-1}=ans_1+ans_2$
$ans_1=\sum_{i=1}^{n-1}\sum_{Sa_i=0}^{Sb_i}(Sb_i-Sa_i)\times {Sa_i+i-1\choose i-1}{V+n-i-Sa_i-1\choose n-i-1}=\sum_{i=1}^{n-1}(B1_i-A1_i)$
$B1_i=Sb_i\times \sum_{Sa_i=0}^{Sb_i}{Sa_i+i-1\choose i-1}{V+n-i-Sa_i-1\choose n-i-1}$
$单独考虑式子G_{B1}(n,V,p,k)=\sum_{i=0}^{k}{i+p-1\choose p-1}{V+n-p-i-1\choose n-p-1}$
$G_{B1}(n,V,p,k+1)=G_{B1}(n,V,p,k)+{k+p\choose p-1}{V+n-p-k-2\choose n-p-1}$
$考虑组合意义,G_{B1}(n,V,p,k)表示前p个盒子小球总数小于等于k的方案数$
$枚举j使得第(k+1)个小球放在j这个盒子里$
$则G_{B1}(n,V,p,k)=\sum_{j=p+1}^n{k-1+j\choose j-1}{V-k-1+n-j\choose n-j}$
$易得G_{B1}(n,V,p+1,k)=G_{B1}(n,V,p,k)-{k+p\choose p}{V-k-2+n-p\choose n-p-1}$
$初始化k=0,p=1,G_{B1}(n,V,p,k)={V+n-2 \choose n-2}$
$于是B1_i得到总复杂度O(n+V)的转移$
$A1_i=\sum_{Sa_i=0}^{Sb_i}Sa_i\times {Sa_i+i-1\choose i-1}{V+n-i-Sa_i-1\choose n-i-1}$
$=\sum_{Sa_i=0}^{Sb_i}Sa_i\times \frac{(Sa_i+i-1)!}{(i-1)!\times (Sa_i)!}{V+n-i-Sa_i-1\choose n-i-1}$
$=\sum_{Sa_i=0}^{Sb_i}i\times \frac{(Sa_i+i-1)!}{i!\times (Sa_i-1)!}{V+n-i-Sa_i-1\choose n-i-1}$
$=i\times \sum_{Sa_i=0}^{Sb_i}{Sa_i+i-1\choose i}{V+n-i-Sa_i-1\choose n-i-1}$
$单独考虑式子G_{A1}(n,V,p,k)=\sum_{i=0}^{k}{i+p-1\choose i-1}{V+n-p-i-1\choose n-p-1}$
$G_{A1}(n,V,p,k)=G_{B1}(n+1,V-1,p+1,k-1)$
$G_{A1}(n,V,p,k+1)=G_{A1}(n,V,p,k)+{k+p\choose p}{V+n-p-k-2\choose n-p-1}$
$G_{A1}(n,V,p+1,k)=G_{A1}(n,V,p,k)-{k+p\choose p+1}{V+n-p-k-2\choose n-p-1}$
$初始化k=0,p=1,G_{A1}(n,V,p,k)=0$
$于是A1_i得到总复杂度O(n+V)的转移$
$于是可以O(n+V)求出ans1$
$ans_2=\sum_{i=1}^{n-1}\sum_{Sa_i=Sb_i}^{V}(Sa_i-Sb_i)\times {Sa_i+i-1\choose i-1}{V+n-i-Sa_i-1\choose n-i-1}=\sum_{i=1}^{n-1}(A2_i-B2_i)$
$B2_i=Sb_i\times \sum_{Sa_i=Sb_i}^V{Sa_i+i-1\choose i-1}{V+n-i-Sa_i-1\choose n-i-1}$
$单独考虑式子G_{B2}(n,V,p,k)=\sum_{i=k}^V{i+p-1\choose p-1}{V+n-p-i-1\choose n-p-1}$
$考虑组合意义,G_{B2}(n,V,p,k)表示前n-p个盒子小球总数小于等于V-k的方案数$
$G_{B2}(n,V,p,k)=G_{B1}(n,V,n-p,V-k)$
$G_{B2}(n,V,p,k+1)=G_{B2}(n,V,p,k)-{k+p-1\choose p-1}{V+n-p-k-1\choose n-p-1}$
$G_{B2}(n,V,p+1,k)=G_{B2}(n,V,p,k)+{k+p-1\choose p}{V+n-p-k-1\choose n-p-1}$
$初始化k=0,p=1,G_{B2}(n,V,p,k)={V+n-1\choose n-1}$
$于是B2_i得到总复杂度O(n+V)的转移$
$A2_i=\sum_{Sa_i=Sb_i}^VSa_i\times {Sa_i+i-1\choose i-1}{V+n-i-Sa_i-1\choose n-i-1}$
$=\sum_{Sa_i=Sb_i}^VSa_i\times \frac{(Sa_i+i-1)!}{(i-1)!\times (Sa_i)!}{V+n-i-Sa_i-1\choose n-i-1}$
$=\sum_{Sa_i=Sb_i}^Vi\times \frac{(Sa_i+i-1)!}{i!\times (Sa_i-1)!}{V+n-i-Sa_i-1\choose n-i-1}$
$=i\times \sum_{Sa_i=Sb_i}^V{Sa_i+i-1\choose i}{V+n-i-Sa_i-1\choose n-i-1}$
$单独考虑式子G_{A2}(n,V,p,k)=\sum_{i=k}^V{i+p-1\choose i-1}{V+n-p-i-1\choose n-p-1}$
$G_{A2}(n,V,p,k)=G_{A1}(n,V,p,V)-G_{A1}(n,V,p,k-1)$
$G_{A2}(n,V,p,k+1)=G_{A2}(n,V,p,k)-{k+p-1\choose k-1}{V+n-p-k-1\choose n-p-1}$
$G_{A2}(n,V,p+1,k)=G_{A2}(n,V,p,k)+{k+p-1\choose p+1}{V+n-p-k-1\choose n-p-1}$
$初始化k=0,p=1,G_{A2}(n,V,p,k)=\sum_{i=0}^Vi{V+n-i-2\choose n-2}$
$这个初始化看得我很不爽,很想O(1)初始化,于是又推一下式子喽:$
$原式=\sum_{i=0}^Vi{V+n-2-i\choose n-2}$
$=\sum_{i=n-2-V}^{n-2}(n-2-i)\times{V+i\choose n-2}$
$=\sum_{i=n-2-V}^{n-2}(n-2)\times{V+i\choose n-2}-\sum_{i=n-2}^{n-2+V}(i-V)\times{i\choose n-2}$
$=V\times \sum_{i=0}^{V}{i+n-2\choose n-2}-(n-1)\times \sum_{i=0}^V{i+n-2\choose n-1}$
$这一步运用上指标求和,即\sum_{i=0}^n{i\choose k}={n+1\choose k+1}。这也是我第一次运用上指标求和$
$原式=V\times {V+n-1\choose V}-(n-1)\times {V+n-1\choose n}$
$=n\times {V+n-1\choose n}-n\times {V+n-1\choose n}+{V+n-1\choose n}$
$={V+n-1\choose n}$
$于是A2_i得到总复杂度O(n+V)的转移$
$于是可以O(n+V)求出ans2$
$于是可以O(n+V)求出ans$
式子推完了,说一下这题的几个关键点。
1、一开始要敢大胆写式子,大胆拆式子。
2、关于 $A1_i,A2_i$ 的转化应该是套路,学着点,把枚举的系数给他消了。
3、$B1_i,B2_i$ 中考虑组合意义确实是神来之笔,多练练吧。
4、式子可以写成函数的形式,然后可以往已经推出来的函数上面转化。感觉这题里的转化方式还不少。
5、个人暂时水平较低,对于组合数中出现负数的情况尽量避免,调整好枚举的变量即可。
三、完整代码:
1 #include<iostream> 2 3 #define N 2500020 4 #define lim 2500010 5 #define ll long long 6 #define mod 998244353 7 #define rep(i,l,r) for(ll i=l;i<=r;i++) 8 #define per(i,r,l) for(int i=r;i>=l;i--) 9 10 using namespace std; 11 12 ll n,ans,A,B,F,G,V; 13 ll p,k,a11,a12,a21,a22; 14 15 ll fac[N],inv[N]; 16 ll a[N],b[N],c[N]; 17 18 ll ksm(ll base,ll q){ 19 ll res=1; while(q){ 20 if(q&1) res*=base,res%=mod; 21 base*=base,base%=mod,q>>=1; 22 } return res; 23 } 24 void add(ll &u,ll v){ 25 u+=v; 26 if(u>=mod) u-=mod; 27 } 28 ll C(ll n,ll m){ 29 if(n<0||m<0||n<m) return 0; 30 return fac[n]*inv[m]%mod*inv[n-m]%mod; 31 } 32 33 ll calc(ll x){ 34 B=n-1;A=B+V-k; 35 if(p<x){ 36 F=C(A-p-1,B-p),G=C(A-p,B-p); 37 add(a21,(C(k+p,p)*F+C(k+p-1,p)*G)%mod); 38 add(a22,(C(k+p,p+1)*F+C(k-1+p,p+1)*G)%mod); 39 p++; 40 } 41 42 B=n-p-1;A=V+B; 43 while(k<b[x]){ 44 F=C(A-k-1,B),G=C(A-k,B); 45 add(a12,(C(k+p,p)*F+C(k+p-1,p)*G)%mod); 46 add(a11,(C(k+p-1,k)*G+C(k+p,p-1)*F)%mod); 47 k++; 48 } 49 return ((mod+a11-a21)*b[x]+(mod+a22-a12)*x)%mod*c[x]%mod; 50 } 51 52 void solve(){ 53 cin>>n; ans=0; 54 55 rep(i,1,n) cin>>b[i]; 56 rep(i,1,n-1) cin>>c[i]; 57 rep(i,1,n) b[i]+=b[i-1]; 58 59 V=b[n]; p=1,k=0,a11=0,a12=0; 60 a21=C(V+n-2,V-1),a22=C(V+n-1,n); 61 62 rep(i,1,n-1) add(ans,calc(i)); 63 cout<<ans<<'\n'; 64 } 65 66 signed main(){ 67 ios::sync_with_stdio(false); 68 cin.tie(0); cout.tie(0); 69 70 fac[0]=1; rep(i,1,lim) fac[i]=fac[i-1]*i%mod; 71 inv[lim]=ksm(fac[lim],mod-2); per(i,lim,1) inv[i-1]=inv[i]*i%mod; 72 73 ll T; cin>>T; 74 rep(i,1,T) solve(); 75 76 return 0; 77 }
四、写题心得:
好题,知识点不难,但题就是难,比较繁琐。
喜欢 $feecle$ 选的题!拜谢。
还是掌握了许多推式子的技巧,收获很大,但太耗时间了$qwq$