链接:戳这里
Problem Description
Alice gets two sequences A and B. A easy problem comes. How many pair of sequence A' and sequence B' are same. For example, {1,2} and {1,2} are same. {1,2,4} and {1,4,2} are not same. A' is a subsequence of A. B' is a subsequence of B. The subsequnce can be not continuous. For example, {1,1,2} has 7 subsequences {1},{1},{2},{1,1},{1,2},{1,2},{1,1,2}. The answer can be very large. Output the answer mod 1000000007.
Input
The input contains multiple test cases.
For each test case, the first line cantains two integers N,M(1≤N,M≤1000). The next line contains N integers. The next line followed M integers. All integers are between 1 and 1000.
Output
For each test case, output the answer mod 1000000007.
Sample Input
3 2
1 2 3
2 1
3 2
1 2 3
1 2
Sample Output
2
3
题意:
分别给出长度为n,m的序列,问有多少子序列a和b相等,ab元素的相对原数组位置一样
思路:
都知道是dp,说清楚点吧
dp[i][j] 表示当前a序列到位置i,b序列到位置j的子序列数目
if(a[i]!=b[j]) dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]
当前a[i]!=b[j] 那么需要继承[1,i]与[1,j-1]的相同子序列数目,同理[1,i-1]与[1,j]也需要继承。但是在继承的时候,多算了[1,i-1]与[1,j-1]的,仔细看看前面的[i-1,j] && [i,j-1]都包含了[i-1,j-1],所以会多算一次,减去就可以了
if(a[i]==b[j]) dp[i][j]=dp[i-1][j]+dp[i][j-1]+1
和前面一样,先不考虑a[i]与b[j]的关系,统计之前的值并继承。dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1],现在来考虑a[i]==b[j]对当前[i,j]的贡献,前面提到了[i-1,j-1]算加了两次,要减掉一次。
这里需要把a[i]这个元素加到一次的[i-1,j-1]上去 ,使得前面的相同子序列用上a[i],然后就有dp[i-1][j-1]次,加上就可以了,至于为什么+1,显然{ a[i] & b[j] }可以单独做一个子序列啊。来组数据模拟一下吧
a:1 2 3 4 5
b:1 3 4 5 1
假设当前枚举到:[4,3] 且a[4]==b[3]
a=1 2 3 4
b=1 3 4
dp[4][3]=dp[4][2]+dp[3][3] (当前没有考虑a[4]==b[3]进去
dp[4][2]&dp[3][3],当前对应的子序列为:{a=1,b=1}、{a=3,b=3}、{a=1,3 , b=1,3 } & {a=1,b=1}、{a=3,b=3}、{a=1,3 , b=1,3 }
显然多算了一次dp[3][2],那么我在多算的这dp[3][2]三次里面加上一个元素a[4]:
{a=1,b=1}、{a=3,b=3}、{a=1,3 , b=1,3 } & {a=1,4 , b=1,4 }、{a=3,4 , b=3,4 }、{a=1,3,4 , b=1,3,4 }
所以不需要减去dp[3][2],后面+1 -> 子序列{4,4}
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include <ctime>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<iomanip>
#include<cmath>
#include<bitset>
#define mst(ss,b) memset((ss),(b),sizeof(ss))
///#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
#define INF (1ll<<60)-1
#define Max 1e9
const ll mod=1000000007;
using namespace std;
int n,m;
ll dp[1010][1010];
int a[1010],b[1010];
int main(){
while(scanf("%d%d",&n,&m)!=EOF){
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=m;i++) scanf("%d",&b[i]);
mst(dp,0);
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;
dp[i][j]%=mod;
}
}
printf("%I64d\n",(dp[n][m]%mod+mod)%mod);
}
return 0;
}