zoukankan      html  css  js  c++  java
  • [AGC013D] Piling Up

    LXXIX.[AGC013D] Piling Up

    一个很naive的思路就是设\(f[i][j]\)表示当前进行了\(i\)步,并且盒子中剩下了\(j\)个白球的方案数,然后直接DP即可。

    但是这样是有问题的——它没有考虑到重复计算的问题。

    我们不妨令\(+\)符号表示取出黑球,\(-\)符号表示取出白球。

    则一种方式是\(6\xrightarrow{+-}6\xrightarrow{--}5\),其中数字表示剩余白球数。

    另一种方式是\(4\xrightarrow{+-}4\xrightarrow{--}3\)。很明显,两者即使盒中球数不同,但是序列是相同的。

    为了避免重复计算,我们可以强制要求只有过程中出现过\(0\)的序列才是合法序列。

    于是我们可以设\(f[i][j][0/1]\)表示进行\(i\)步,盒子中剩下\(j\)个白球,且(没有/有)到过\(0\)的方案数。则答案即为\(\sum\limits_{i=0}^nf[m][i][1]\)

    要注意的是,这里的转移过程必须保证任意时刻球的数量必须在\([0,n]\)范围之内,因此对于不合法的状态要记得特判掉。

    复杂度\(O(nm)\)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int mod=1e9+7;
    int n,m,f[3010][3010][2],res;//0: haven't reached 0; 1:have reached 0
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=0;i<=n;i++)f[0][i][i==0]=1;
    	for(int i=0;i<m;i++)for(int j=0;j<=n;j++){
    		if(j)(f[i+1][j][j==1]+=f[i][j][0])%=mod,(f[i+1][j][1]+=f[i][j][1])%=mod;//-+
    		if(j)(f[i+1][j-1][j==1]+=f[i][j][0])%=mod,(f[i+1][j-1][1]+=f[i][j][1])%=mod;//--;
    		if(j<n)(f[i+1][j][0]+=f[i][j][0])%=mod,(f[i+1][j][1]+=f[i][j][1])%=mod;//+-;
    		if(j<n)(f[i+1][j+1][0]+=f[i][j][0])%=mod,(f[i+1][j+1][1]+=f[i][j][1])%=mod;//++;
    	}
    	for(int i=0;i<=n;i++)(res+=f[m][i][1])%=mod;
    	printf("%d\n",res);
    	return 0;
    }
    

  • 相关阅读:
    mybatis generator插件开发
    webserver实现
    Linux的selinux
    oracle从备份归档日志的方法集中回收
    百度地图 Android SDK
    Oracle实践--PL/SQL表分区的基础
    js插件---jquery给表格添加行列
    m_Orchestrate learning system---三十四、使用重定义了$的插件的时候最容易出现的问题是什么
    2018十大国产佳片
    javascript对象使用总结
  • 原文地址:https://www.cnblogs.com/Troverld/p/14598455.html
Copyright © 2011-2022 走看看