当前位置:网站首页>杭电多校3 1012. Two Permutations dp*
杭电多校3 1012. Two Permutations dp*
2022-08-01 22:16:00 【Strezia】
1012
dp
题意
给出长度为 n n n 的全排列 p , q p,q p,q,还有一个由 p , q p,q p,q 组成的长度为 2 × n 2\times n 2×n 的序列 S S S 。
现在有一个空序列 R R R ,每次可以从 p p p 或 q q q 的开头取出一个数字并加到 R R R 的末尾,问有多少种取法使得 R = S R = S R=S 。
思路
记 d p [ x ] [ y ] dp[x][y] dp[x][y] 表示 p , q p,q p,q 中分别取前 x , y x,y x,y 位时的方案数。则 d p [ x ] [ y ] = d p [ x + 1 ] [ y ] + d p [ x ] [ y + 1 ] dp[x][y] = dp[x+1][y]+dp[x][y+1] dp[x][y]=dp[x+1][y]+dp[x][y+1] ,前者需满足 p [ x + 1 ] = s [ x + y + 1 ] p[x+1]=s[x+y+1] p[x+1]=s[x+y+1] ,后者需满足 q [ y + 1 ] = s [ x + y + 1 ] q[y+1] = s[x+y+1] q[y+1]=s[x+y+1] 。
但因为空间不够,无法开二维数组(当然也可以用 std::map,但常数比较大),所以改成 d p [ 2 × m a x n ] [ 2 ] dp[2\times maxn][2] dp[2×maxn][2] ,其中 d p [ i ] [ 0 / 1 ] dp[i][0/1] dp[i][0/1] 表示两数组一共匹配了 i i i 位且目前最后一位匹配的是 p / q p/q p/q 的方案数。转移也类似写就可以,代码如下:
int dfs(int x, int y, int t) {
if(x == n && y == n) return 1;
if(dp[x + y + 1][t] != -1) return dp[x + y + 1][t];
int ans = 0;
if(p[x + 1] == s[x+y+1] && x < n) {
ans += dfs(x + 1, y, 0);
ans %= P;
}
if(q[y + 1] == s[x+y+1] && y < n) {
ans += dfs(x, y + 1, 1);
ans %= P;
}
return dp[x+y+1][t] = ans;
}
//调用
int ans = 0;
if (p[1] == s[1])ans += dfs(1, 0, 0), ans %= P;
if (q[1] == s[1])ans += dfs(0, 1, 1), ans %= P;
这个代码看起来是 O ( n 2 ) O(n^2) O(n2) ,实际上是 O ( n ) O(n) O(n) ,因为 s s s 中每个数都只出现了两次(如果不是直接0),且在 p , q p,q p,q 中各出现一次,也就是 s s s 中同一个位置最多和两个位置(p,q中对应的位置)匹配,因为 s s s 长度为 2 × n 2\times n 2×n ,所以时间复杂度为 O ( 4 n ) O(4n) O(4n)。
代码
int n;
int dp[maxn << 1][2], p[maxn], q[maxn];
int s[maxn << 1];
int dfs(int x, int y, int t) {
if(x == n && y == n) return 1;
if(dp[x + y + 1][t] != -1) return dp[x + y + 1][t];
int ans = 0;
if(p[x + 1] == s[x+y+1] && x < n) {
ans += dfs(x + 1, y, 0);
ans %= P;
}
if(q[y + 1] == s[x+y+1] && y < n) {
ans += dfs(x, y + 1, 1);
ans %= P;
}
return dp[x+y+1][t] = ans;
}
void solve() {
cin >> n;
for(int i = 1; i <= n * 2; i++) dp[i][0] = dp[i][1] = -1;
for(int i = 1;i <= n; i++) cin >> p[i];
for(int i = 1;i <= n; i++) cin >> q[i];
for(int i = 1;i <= n * 2; i++) cin >> s[i];
int ans = 0;
if (p[1] == s[1])ans += dfs(1, 0, 0), ans %= P;
if (q[1] == s[1])ans += dfs(0, 1, 1), ans %= P;
cout << ans << endl;
}
边栏推荐
- JS prototype hasOwnProperty in Add method Prototype end point Inherit Override parent class method
- 编曲软件FL studio20.8中文版功能和作用
- 【C语言】猜数字小游戏
- 联邦学习在金融领域的发展和应用
- 小程序毕设作品之微信体育馆预约小程序毕业设计成品(2)小程序功能
- 选择合适的 DevOps 工具,从理解 DevOps 开始
- 【牛客刷题-SQL大厂面试真题】NO4.出行场景(某滴打车)
- Postman batch test interface detailed tutorial
- Shell programming conditional statement
- AQS
猜你喜欢

LeetCode952三部曲之二:小幅度优化(137ms -> 122ms,超39% -> 超51%)

今年的很美味

编曲软件FL studio20.8中文版功能和作用

Raspberry Pi information display small screen, display time, IP address, CPU information, memory information (C language), four-wire i2c communication, 0.96-inch oled screen

小程序毕设作品之微信体育馆预约小程序毕业设计成品(2)小程序功能

Flutter基础学习(一)Dart语言入门

Postman 批量测试接口详细教程

【C语言实现】两种计算平均成绩题型,博主精心整理,值得一读

复现gallerycms字符长度限制短域名绕过

论文解读(GSAT)《Interpretable and Generalizable Graph Learning via Stochastic Attention Mechanism》
随机推荐
SOM网络2: 代码的实现
罗克韦尔AB PLC RSLogix5000中的比较指令使用方法介绍
统计单词数
字符串——Trie
今年的很美味
图论——强连通分量缩点+拓扑排序
不卷了!入职字节跳动一周就果断跑了。
求解多元多次方程解的个数
联邦学习的框架搭建
LeetCode952三部曲之二:小幅度优化(137ms -> 122ms,超39% -> 超51%)
more grown, more lonely
APP special test: traffic test
【建议收藏】ヾ(^▽^*)))全网最全输入输出格式符整理
VGUgarbage collector(垃圾回收器)的实现原理
找工作必备!如何让面试官对你刮目相看,建议收藏尝试!!
SOM Network 2: Implementation of the Code
Small application project works WeChat stadium booking applet graduation design of the finished product (1) the development profile
小程序毕设作品之微信美食菜谱小程序毕业设计成品(5)任务书
KMP 字符串匹配问题
Today's sleep quality record 74 points