zoukankan      html  css  js  c++  java
  • 前缀和优化DP

    前缀和优化DP

    例1: [洛谷P2513 HAOI2009]逆序对数列

    (f[i][j]) 表示 前i个数字构成逆序对数为 j 的方案总数

    [f[i][j]=sum_{k=max(0,j-i-1)}^{j}{f[i][k]}\ 令sum=sum_{k=max(0,j-i-1)}^{j}{f[i][k]} ]

    每次只需要 sum+ $ f[i-1][j] $ 再让$ f[i][j] $ =sum;

    然后sum 右移 再 减去 $ f[i-1][j-i-1] $

    #include <iostream>
    #include <cstdio>
    using namespace std;
    int n,k;
    const int p=10000;
    int f[2000][2000],sum;
    int main() {
        scanf("%d%d",&n,&k);
        f[1][0]=1;
        for(int i=2;i<=n;sum=0,i++)
            for(int j=0;j<=k;j++) {
                sum=(sum+f[i-1][j])%p;
                f[i][j]=sum;
                if(j-i+1>=0)sum=(sum-f[i-1][j-i+1]+p)%p;
            }
        printf("%d
    ",f[n][k]);
        return 0;
    }
    

    例2:染色

    $ dp[i][j]$ 表示考虑前 i 个位置,([i-j+1,i])中的颜色互不相同,并且(a_i-j)与这段区间中的某一个位置颜色相同

    我们枚举第(i+1)个位置和([i-j+1,i])中的哪一个颜色相同或者全部不同,进行转移

    $ dp[i+1][k]+=dp[i][j](1<=k<=j) $

    $ dp[i+1][j+1]=dp[i][j]*(m-j) $

    这样的话时间复杂度是(O(N^3))

    发现第二个转移可以前缀和优化一下,显然 $ dp[i+1][k]$ 可以从 (dp[i][k-(m-1)])转移而来

    时间复杂度(O(N^2))

    #include <cstdio>
    #include <iostream>
    using namespace std;
    typedef long long LL;
    LL f[5010][5010],m,n,s,p;
    int main() {
    	scanf("%lld%lld%lld",&n,&m,&p);
    	f[0][0]=1;
    	for(int i=1;i<=n;i++) { 
    		s=0;
    		for(int j=m-1;j;j--){
    			s=(s+f[i-1][j])%p;
    			f[i][j]=(s+f[i-1][j-1]*(m-j+1))%p;
    		}
    	}
    	s=0;
    	for(int i=1;i<=m;i++)	
    		s=(s+f[n][i])%p;
    	printf("%lld
    ",s);
    	return 0;
    }
    
    
  • 相关阅读:
    U盘安装Ubuntu 14.04 LTS
    VS2013配置OPENCV2.4.9(OPENCV3.X)
    make、makefile、cmake、qmake对比
    Google C++ Style
    Ubuntu16.04搜狗输入法无法输入中文
    Ubuntu16.04安装使用wineqq
    Ubuntu卸载软件
    [机器学习入门篇]-梯度下降法
    [机器学习入门篇]-正则化
    2014年度最受好评的十佳工具
  • 原文地址:https://www.cnblogs.com/ke-xin/p/13509601.html
Copyright © 2011-2022 走看看