• LuoguP5075 [JSOI2012]分零食


    题意

    (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} imes(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} imes(Ok^2+Sk+U)\ =sum_{k=2}^{j-i+1}f_{i-1,j-k} imes[O(k-1)^2+S(k-1)+U]\ =sum_{k=2}^{j-i+1}f_{i-1,j-k} imes(Ok^2+Sk+U)- sum_{k=2}^{j-i+1}f_{i-1,j-k} imes(2Ok-O+S)\ =f_{i,j}-f_{i-1,j-1} imes(O+S+U)- sum_{k=2}^{j-i+1}f_{i-1,j-k} imes(2Ok-O+S) ]

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

    [f_{i,j-1}= f_{i,j}-f_{i-1,j-1} imes(O+S+U)-g_{i,j}+f_{i-1,j-1} imes(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} imes(2Ok-O+S)\ =sum_{k=2}^{j-i+1}f_{i-1,j-k} imes[2O(k-1)-O+S]\ =sum_{k=2}^{j-i+1}f_{i-1,j-k} imes(2Ok-O+S)- sum_{k=2}^{j-i+1}f_{i-1,j-k} imes 2O\ =g_{i,j}-f_{i-1,j-1} imes(O+S)- sum_{k=2}^{j-i+1}f_{i-1,j-k} imes 2O ]

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

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

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

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

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

    #include<bits/stdc++.h>
    #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<=ed;++i)
    using namespace std;
    typedef cn int cint;
    il int rd(){
       rg int x(0),f(1); rg char c(gc);
       while(c<'0'||'9'<c){ if(c=='-') f=-1; c=gc; }
       while('0'<=c&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=gc;
       return x*f;
    }
    template<typename T> 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<<1)%mod;
    	
    	f[0][0]=1;
    	fp(i,1,min(m,A)){
    		h[nw][i-1]=g[nw][i-1]=f[nw][i-1]=0;
    		fp(j,i,m){
    			h[nw][j]=(h[nw][j-1]+hh*f[pv][j-1])%mod;
    			g[nw][j]=(g[nw][j-1]+gg*f[pv][j-1]+h[nw][j])%mod;
    			f[nw][j]=(f[nw][j-1]+ff*f[pv][j-1]+g[nw][j])%mod;
    		}
    		ans=(ans+f[nw][m])%mod;
    		nw^=pv^=nw^=pv;
    	}
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    Linux进入单用户模式(passwd root修改密码)
    stark组件的分页,模糊查询,批量删除
    stark组件的增删改(新)
    stark组件的增删改
    stark组件之展示数据(查)
    stark组件配置,二层URL
    单例模式及设计url分发
    Django之modelform
    rbac组件权限按钮,菜单,可拔插
    rbac权限+中间件
  • 原文地址:https://www.cnblogs.com/akura/p/12259557.html
Copyright © 2020-2023  润新知