2021-2022-1 ACM集训队每周程序设计竞赛 - 问题 E: 数学!- 题解

Posted Tisfy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-2022-1 ACM集训队每周程序设计竞赛 - 问题 E: 数学!- 题解相关的知识,希望对你有一定的参考价值。


数学!

时间限制:1秒
空间限制:128M


题目描述

给你两个长度分别为 n n n m m m的数组 S S S T T T,问你 S S S的子序列有多少和 T T T的子序列相同。

此题子序列不要求连续,即:从序列 a a a中删除 0 0 0 l e n ( a ) len(a) len(a)个元素后得到的序列即为 a a a的子序列。


输入描述

第一行空格隔开的两个正整数 n n n m m m,分别代表序列 S S S的长度和序列 T T T的长度。

第二行 n n n个空格隔开的正整数,代表序列 S S S

第三行 m m m个空格隔开的正整数,代表序列 T T T

输入格式如下:

n m
S1 S2 ... S3
T1 T2 ... T3s

其中:

  • 1 ≤ n , m ≤ 2 × 1 0 3 1\\leq n,m\\leq2\\times10^3 1n,m2×103
  • 1 ≤ S i , T i ≤ 1 0 5 1\\leq S_i, T_i\\leq 10^5 1Si,Ti105
  • 所有输入的数都为正整数

输出描述

输出一行一个正整数代表序列 S S S和序列 T T T的相同子序列的个数,答案对 1 0 9 + 7 10^9+7 109+7取模。


样例一

输入

2 2
1 3
3 1

输出

3

样例二

输入

2 2
1 1
1 1

输出

6

提示

样例一中,
序列 S S S 4 4 4个子序列: ( ) , ( 1 ) , ( 3 ) , ( 1 , 3 ) (),(1),(3),(1,3) (),(1),(3),(1,3)
序列 T T T 4 4 4个子序列: ( ) , ( 3 ) , ( 1 ) , ( 3 , 1 ) (),(3),(1),(3,1) (),(3),(1),(3,1)

相同子序列有 3 3 3对: ( ) , ( 1 ) , ( 3 ) (),(1),(3) (),(1),(3)


题目分析

这道题可以使用动态规划。
用数组 d p [ i ] [ j ] dp[i][j] dp[i][j] 表示序列 S S S的前 i i i个数 及 序列 T T T的前 j j j个数 的相同子序列的个数(即问题所问)

那么因为可以有空的子序列,所以 d p [ ∗ ] [ 0 ] dp[*][0] dp[][0]都等于 1 1 1 d p [ 0 ] [ ∗ ] dp[0][*] dp[0][]也都等于 1 1 1(一个一定长度的序列和一个空序列的相同子序列为空的序列)

  • S [ i ] ≠ T [ j ] S[i]\\neq T[j] S[i]=T[j]时,有转移方程: d p [ i ] [ j ] = d p [ i − 1 ] [ j ] + d p [ i ] [ j − 1 ] − d p [ i − 1 ] [ j − 1 ] dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1] dp[i][j]=dp[i1][j]+dp[i][j1]dp[i1][j1],即为 S S S的前 i − 1 i-1 i1个元素和 T T T的前 j j j个元素的相同子序列数+ S S S的前 i i i个元素和 T T T的前 j − 1 j-1 j1个元素的相同子序列数。
    但是 S S S的前 i i i个元素和 T T T的前 j j j个元素计算了两次,根据容斥原理,我们需要再减去 S S S的前 i i i个元素和 T T T的前 j j j个元素的相同子序列的个数。

  • S [ i ] = T [ j ] S[i]= T[j] S[i]=T[j]时,序列 S S S的前 i − 1 i-1 i1个元素和序列 T T T的前 j − 1 j-1 j1个元素的任意一个公共子序列同时加上 S [ i ] S[i] S[i]得到的新的序列也相同。此时转移方程为 d p [ i ] [ j ] = d p [ i − 1 ] [ j ] + d p [ i ] [ j − 1 ] − d p [ i − 1 ] [ j − 1 ] + d p [ i − 1 ] [ j − 1 ] = d p [ i − 1 ] [ j ] + d p [ i ] [ j − 1 ] dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+dp[i-1][j-1]=dp[i-1][j]+dp[i][j-1] dp[i][j]=dp[i1][j]+dp[i][j1]dp[i1][j1]+dp[i1][j1]=dp[i1][j]+dp[i][j1]

综上,我们有转移方程 d p [ i ] [ j ] = d p [ i − 1 ] [ j ] + d p [ i ] [ j − 1 ] dp[i][j]=dp[i-1][j]+dp[i][j-1] dp[i][j]=dp[i1][j]+dp[i][j1],而当 S [ i ] ≠ T [ j ] S[i]\\neq T[j] S[i]=T[j]时,需要减去一个 d p [ i − 1 ] [ j − 1 ] dp[i-1][j-1] dp[i1][j1]


AC代码

#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i <= r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;

const ll mod = 1e9 + 7;
ll dp[2010][2010] = {1};
int a[2010], b[2010];以上是关于2021-2022-1 ACM集训队每周程序设计竞赛 - 问题 E: 数学!- 题解的主要内容,如果未能解决你的问题,请参考以下文章

BUCT - 2021-2022-1 ACM集训队每周程序设计竞赛(10)题解

BUCT - 2021-2022-1 ACM集训队每周程序设计竞赛题解

BUCT - 2021-2022-1 ACM集训队每周程序设计竞赛题解

BUCT - 2021-2022-1 ACM集训队每周程序设计竞赛题解

2021-2022-1 ACM集训队每周程序设计竞赛题解

2021-2022-1 ACM集训队每周程序设计竞赛题解