多校聯合訓練&hdu5791 Two

hdu5791php

dp[i][j]表示的是序列A前i個數字和序列B前j個數字的公共子序列的總個數,那麼的dp公式就能夠這麼表示ios

理解一下此公式若最尾部的a[i]和b[j]相等的話,那麼單獨的a[i]和b[j]組成1個相同子序列。spa

同時咱們能夠想一下以前的前i-1個子序列和前j-i個子序列再加上a[i]又能組成dp[i-1]個公共子序列。code

固然了,包含第i個數字的前i個序列a和前j-1個數字的序列b以及包含第j個數字的前j個序列b和前i-1個數字的序列a也要算上。blog

因此把上面3種狀況一合併就是前i-1個子序列a和前j個子序列b的公共子序列個數加上前i個子序列a和前j-1個子序列b的公共子序列個數再加1。get

這裏包含了2倍的dp[i-1][j-1]個數。string

若是a[i]和b[j]不相等的話,減去一個dp[i-1][j-1]個數便可。io

本題中另外一個注意點就是dp[i][j]可能爲負,此時的處理方法是加上一個MODclass

代碼以下:stream

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define MOD 1000000007
 5 #define LL long long
 6 using namespace std;
 7 LL dp[1005][1005];
 8 LL a[1005];
 9 LL b[1005];
10 int main()
11 {
12     int n,m;
13     while(~scanf("%d%d",&n,&m))
14     {
15         memset(dp,0,sizeof(dp));
16         for(int i = 1;i<=n;i++)
17             scanf("%d",&a[i]);
18         for(int j = 1;j<=m;j++)
19             scanf("%d",&b[j]);
20         for(int i = 1;i<=n;i++)
21         {
22             for(int j = 1;j<=m;j++)
23             {
24                 if(a[i]==b[j])
25                     dp[i][j]+=dp[i-1][j]+dp[i][j-1]+1;
26                 else
27                     dp[i][j]+=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1];//極有可能出現負數
28                 if(dp[i][j]<0)
29                     dp[i][j]+=MOD;
30                 dp[i][j]=dp[i][j]%MOD;
31             }
32         }
33         printf("%I64d\n",dp[n][m]);
34     }
35     return 0;
36 }
相關文章
相關標籤/搜索