当前位置:网站首页>杭电多校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;
}
边栏推荐
- 【C语言】猜数字小游戏
- 小程序毕设作品之微信美食菜谱小程序毕业设计成品(6)开题答辩PPT
- 如何理解 new (...args: any[]) => any
- Yizhou Financial Analysis | The intelligent transformation of bank ATM machines is accelerated; the new Internet loan regulations bring challenges
- KMP 字符串匹配问题
- [机缘参悟-58]:《素书》-5-奉行仁义[遵义章第五]
- 恒星的正方形问题
- 越长大越孤单
- 小程序毕设作品之微信体育馆预约小程序毕业设计成品(2)小程序功能
- Lecture 3: Several common table field data types in MySQL database
猜你喜欢

ARFoundation Getting Started Tutorial U2-AR Scene Screenshot Screenshot

blender3.2.1 unit setting

今日睡眠质量记录74分

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

HCIP---Multiple Spanning Tree Protocol related knowledge points

SOM Network 2: Implementation of the Code

xctf攻防世界 Web高手进阶区 webshell

深度学习Course2第二周Optimization Algorithms习题整理

xctf攻防世界 Web高手进阶区 web2

【C语言实现】两种计算平均成绩题型,博主精心整理,值得一读
随机推荐
HCIP---Multiple Spanning Tree Protocol related knowledge points
kubernetes CoreDNS全解析
How to add a game character to a UE4 scene
Flutter基础学习(一)Dart语言入门
User Experience | How to Measure User Experience?
基于 OData 模型和 JSON 模型的 SAP UI5 表格控件行项目的添加和删除实现
小程序中的多表联合查询
Wechat Gymnasium Reservation Mini Program Graduation Design Finished Work Mini Program Graduation Design Finished Product (2) Mini Program Function
seaborn笔记:可视化统计关系(散点图、折线图)
今日睡眠质量记录74分
毕业十年,财富自由:那些比拼命努力更重要的事,从来没人会教你
ARFoundation Getting Started Tutorial U2-AR Scene Screenshot Screenshot
NgRx Selector 的 Memoization 特性学习笔记
威纶通触摸屏如何打开并升级EB8000旧版本项目并更换触摸屏型号?
JS prototype hasOwnProperty in Add method Prototype end point Inherit Override parent class method
Prufer序列
【C语言实现】整数排序-四种方法,你都会了吗、
No more rolls!After joining ByteDance for a week, he ran decisively.
自建 Prometheus 采集腾讯云容器服务监控数据最佳实践
找工作必备!如何让面试官对你刮目相看,建议收藏尝试!!