多校的一道DP水题
题意大概是给你A和B两个数字序列,要你求A序列和B序列不同子序列相同的个数。
输入A序列的长度N和B序列的长度M
比如
1 1
1 1
他的答案应该是 5
一般动规题就是找出状态和状态转移方程
这题状态好找,就是dp[A序列的前i个元素][B序列的前j个元素]
但是怎么转移呢?
首先考虑A[i]不等于B[j]的情况,不等于的话,由容斥原理可知道
dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1]
然后就是如果A[i]等于B[j]的话,是不是前面dp[i-1][j-1]的情况又可以多加一次,然后再加单独A[i]等于B[j]这个情况,就是
dp[i][j] = dp[i-1][j] + dp[i][j-1] + 1
代码如下
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define LL __int64
using namespace std;
const int mod = 1000000007;
LL dp[1010][1010];
int a[1010],b[1010];
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m)){
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=m;i++) scanf("%d",&b[i]);
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i]==b[j]) dp[i][j] = (dp[i-1][j] + dp[i][j-1] + 1)%mod;
else dp[i][j] = (dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] + mod) %mod;//这里有点坑,一般想不到会出现负数
}
}
printf("%I64d\n",dp[n][m]%mod);
}
return 0;
}