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;
}

浙公网安备 33010602011771号