BZOJ 4742: [Usaco2016 Dec]Team Building DP

令 $f[i][j][k]$ 表示 $fj$ 扫到 $i$,$fp$ 扫到 $j$,已经选了 $k$ 个身高的所有状态的前缀和.  

我们有 $f[i][j][k]=f[i-1][j][k]+f[i][j-1][k]-f[i-1][j-1][k]$,这步是一个简单的容斥.    

然后如果有 $fj[i]=fp[j]$ 的话可以直接得到:$f[i][j][k]=f[i][j][k]+f[i-1][j-1][k-1]$  

code:

#include <cstdio>  
#include <cstring>
#include <algorithm>  
#define N 1007 
#define ll long long 
#define mod 1000000009   
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;   
ll f[N][N][11]; 
int fj[N],fp[N]; 
int main() 
{ 
    // setIO("input");     
    int i,j,n,m,K; 
    scanf("%d%d%d",&n,&m,&K);   
    for(i=1;i<=n;++i) scanf("%d",&fj[i]); 
    for(i=1;i<=m;++i) scanf("%d",&fp[i]);           
    for(i=0;i<=n;++i) for(j=0;j<=m;++j)  f[i][j][0]=1;  
    for(int k=1;k<=K;++k) 
    {     
        for(i=1;i<=n;++i) 
        {
            for(j=1;j<=m;++j) 
            {
                (f[i][j][k]+=(f[i-1][j][k]+f[i][j-1][k]-f[i-1][j-1][k]+mod)%mod)%=mod;           
                if(fj[i]>fp[j]) (f[i][j][k]+=f[i-1][j-1][k-1])%=mod; 
            }
        }
    }
    printf("%lld\n",f[n][m][K]);  
    return 0; 
}

  

posted @ 2020-01-02 20:24  EM-LGH  阅读(125)  评论(0编辑  收藏  举报