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