LuoguP5075 [JSOI2012]分零食

2021-04-20 13:27

阅读:343

标签:namespace   getch   oam   ace   pac   clu   names   而且   c++   

题意

\(A\)个人,\(m\)个糖,你可以选择一个\(k\),使第\(1\)~\(k\)个人每个人至少得到一个糖,并且第\(k+1\)~\(A\)个人都得不到糖。\(m\)个糖必须给完。对于每个方案都有一个欢乐值,欢乐值=\(\prod_{i=1}^kOx_i^2+Sx_i+U\),其中\(OSU\)都是给定的系数,\(x_i\)为第\(i\)个人拿到的糖的数量。求所有方案的欢乐值的和。


这题不用NTT啊......

有个比较naive的\(dp\):设\(f_{i,j}\)表示前\(i\)个人一共拿到了\(j\)个糖的所有方案的欢乐值之和,那么有转移方程:

\[ f_{i,j}=\sum_{k=1}^{j-i+1}f_{i-1,j-k}\times(Ok^2+Sk+U) \]

初始值可以设\(f_{0,0}=1\)。这个\(dp\)的复杂度就是\(O(Am^2)\)。一个优化就是,由于最多前\(m\)个人拿到糖(每个人至少拿一个糖),所以\(i\)只用枚举到\(min(m,A)\),复杂度为\(O(m^3)\)

观察转移方程的结构,可以发现这样一个优化:

\[ f_{i,j-1}=\sum_{k=1}^{j-i}f_{i-1,j-1-k}\times(Ok^2+Sk+U)\=\sum_{k=2}^{j-i+1}f_{i-1,j-k}\times[O(k-1)^2+S(k-1)+U]\=\sum_{k=2}^{j-i+1}f_{i-1,j-k}\times(Ok^2+Sk+U)- \sum_{k=2}^{j-i+1}f_{i-1,j-k}\times(2Ok-O+S)\ =f_{i,j}-f_{i-1,j-1}\times(O+S+U)- \sum_{k=2}^{j-i+1}f_{i-1,j-k}\times(2Ok-O+S) \]

观察最后这个\(\sum\),设\(g_{i,j}=\sum_{k=1}^{j-i+1}f_{i-1,j-k}\times(2Ok-O+S)\);那么求\(f\)的式子可以写成:

\[ f_{i,j-1}= f_{i,j}-f_{i-1,j-1}\times(O+S+U)-g_{i,j}+f_{i-1,j-1}\times(O+S)\=f_{i,j}-Uf_{i-1,j-1}-g_{i,j} \]

那么\(f_{i,j}=f_{i,j-1}+Uf_{i-1,j-1}+g_{i,j}\)

\(f\)的转移变成\(O(1)\)的了。但\(g\)还是\(O(n)\)的。观察\(g\)的结构,可以类似地写出求\(g\)的优化:

\[ g_{i,j-1}=\sum_{k=1}^{j-i}f_{i-1,j-1-k}\times(2Ok-O+S)\=\sum_{k=2}^{j-i+1}f_{i-1,j-k}\times[2O(k-1)-O+S]\=\sum_{k=2}^{j-i+1}f_{i-1,j-k}\times(2Ok-O+S)- \sum_{k=2}^{j-i+1}f_{i-1,j-k}\times 2O\=g_{i,j}-f_{i-1,j-1}\times(O+S)- \sum_{k=2}^{j-i+1}f_{i-1,j-k}\times 2O \]

观察最后这个\(\sum\),设\(h_{i,j}=\sum_{k=1}^{j-i+1}f_{i-1,j-k}\times 2O\);那么求\(g\)的式子可以写成:

\[ g_{i,j-1}= g_{i,j}-f_{i-1,j-1}\times(O+S)-h_{i,j}+f_{i-1,j-1}\times 2O\=g_{i,j}-f_{i-1,j-1}\times(S-O)-h_{i,j} \]

那么\(g_{i,j}=g_{i,j-1}+f_{i-1,j-1}\times(S-O)+h_{i,j}\)

每个\(g\)也可以\(O(1)\)求了,而且注意到\(h\)就是前缀和,每个\(h\)也可以\(O(1)\)求,所以整个\(dp\)被优化到了\(O(m^2)\)

可以通过吗?时间上,复杂度虽然是\(O(m^2)\)的,但实际上由于\(i\leq j\),所以只需要循环\(\frac{m\times(m+1)}{2}\)次,也就是\(5\times 10^7\)级别,是可以过的。空间上,加上滚动数组优化也能过。

#include
#define rg register
#define il inline
#define cn const
#define gc getchar()
#define fp(i,a,b) for(rg int i=(a),ed=(b);i il void ckmin(T &x,cn T &y){ if(x>y)x=y; }
cint maxn=10010;

int A,m,mod,O,S,U,ff,gg,hh,ans;
int f[2][maxn],g[2][maxn],h[2][maxn],pv=0,nw=1;

int main(){
    m=rd(),mod=rd(),A=rd(),O=rd(),S=rd(),U=rd();
    ff=U,gg=(S-O+mod)%mod,hh=(O

LuoguP5075 [JSOI2012]分零食

标签:namespace   getch   oam   ace   pac   clu   names   而且   c++   

原文地址:https://www.cnblogs.com/akura/p/12259557.html

上一篇:MVC08

下一篇:深入HTTP


评论


亲,登录后才可以留言!