当前位置: 首页 > ai >正文

洛谷 P1758 [NOI2009] 管道取珠(DP)

题目链接

https://www.luogu.com.cn/problem/P1758

思路

对于 ∑ a i 2 \sum a_{i}^{2} ai2可以换一种理解方式:两个人在两个独立的管道中取球,输出序列相同的方案数。

因为对于每一种输出序列,第一个人有 a i a_{i} ai种方案,第二个人有 a i a_{i} ai种方案,那么两个人输出序列相同的方案总数就是​ ∑ a i 2 \sum a_{i}^{2} ai2

我们定义 f [ k ] [ i ] [ j ] f[k][i][j] f[k][i][j]表示两个人都各取了 k k k个球,第一个人在上管道取了 i i i个球,第二个人在上管道取了 j j j个球,两个人的输出序列相同的方案数。最后的答案就是 f [ n + m ] [ n ] [ m ] f[n+m][n][m] f[n+m][n][m]

因为两个人取的球的数目相同才能发生转移,所以讨论两个人当前从哪个管道中取的球,状态转移方程为:

  • f [ k ] [ i ] [ j ] + = f [ k − 1 ] [ i − 1 ] [ j − 1 ] × ( a [ i ] = = a [ j ] ) f[k][i][j] += f[k-1][i - 1][j - 1] \times (a[i] == a[j]) f[k][i][j]+=f[k1][i1][j1]×(a[i]==a[j])
  • f [ k ] [ i ] [ j ] + = f [ k − 1 ] [ i − 1 ] [ j ] × ( a [ i ] = = b [ k − j ] ) f[k][i][j] += f[k-1][i - 1][j] \times (a[i] == b[k - j]) f[k][i][j]+=f[k1][i1][j]×(a[i]==b[kj])
  • f [ k ] [ i ] [ j ] + = f [ k − 1 ] [ i ] [ j − 1 ] × ( b [ k − i ] = = a [ j ] ) f[k][i][j] += f[k-1][i][j - 1] \times (b[k - i] == a[j]) f[k][i][j]+=f[k1][i][j1]×(b[ki]==a[j])
  • f [ k ] [ i ] [ j ] + = f [ k − 1 ] [ i ] [ j ] × ( b [ k − i ] = = b [ k − j ] ) f[k][i][j] += f[k-1][i][j] \times (b[k - i] == b[k - j]) f[k][i][j]+=f[k1][i][j]×(b[ki]==b[kj])

时间复杂度: O ( n 3 ) O(n^3) O(n3)

代码

#define _USE_MATH_DEFINES
#include <bits/stdc++.h>using namespace std;constexpr long double pi = static_cast<long double>(M_PI);#define int long long
#define double long double
#define endl "\n"typedef long long i64;
typedef unsigned long long u64;
typedef __int128 i128;
typedef pair<int, int> pii;
typedef tuple<int, int, int> tiii;const int N = 2e3 + 5, M = 5e3 + 15;
const int mod = 1024523;
const i64 inf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-8;std::mt19937 rnd(time(0));int n, m;
char a[N], b[N];
int f[2][N][N];
void solve(int test_case)
{cin >> n >> m;for (int i = 1; i <= n; i++){cin >> a[i];}for (int i = 1; i <= m; i++){cin >> b[i];}reverse(a + 1, a + 1 + n);reverse(b + 1, b + 1 + m);f[0][0][0] = 1;for (int k = 1; k <= n + m; k++){int idx = k & 1;for (int i = 0; i <= n; i++){for (int j = 0; j <= n; j++){f[idx][i][j] = 0;}}for (int i = max(0LL, k - m); i <= min(n, k); i++){for (int j = max(0LL, k - m); j <= min(n, k); j++){if (i && j && a[i] == a[j]){f[idx][i][j] += f[idx ^ 1][i - 1][j - 1];f[idx][i][j] %= mod;}if (i && k - j && a[i] == b[k - j]){f[idx][i][j] += f[idx ^ 1][i - 1][j];f[idx][i][j] %= mod;}if (k - i && j && b[k - i] == a[j]){f[idx][i][j] += f[idx ^ 1][i][j - 1];f[idx][i][j] %= mod;}if (k - i && k - j && b[k - i] == b[k - j]){f[idx][i][j] += f[idx ^ 1][i][j];f[idx][i][j] %= mod;}}}}cout << f[(n + m) & 1][n][n] << endl;
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int test = 1;// cin >> test;for (int i = 1; i <= test; i++){solve(i);}return 0;
}
http://www.xdnf.cn/news/11762.html

相关文章:

  • 小型民用AUV用途与研究
  • Linux RPC 和 NFS 教程
  • postman自动化测试
  • 玄机-日志分析-IIS日志分析
  • 网络各类型(BMA,NBMA,P2P)
  • Apache POI操作Excel详解
  • 微信小程序实现运动能耗计算
  • 区域徘徊检测算法AI智能分析网关V4助力公共场所/工厂等多场景安全升级
  • 时序数据库IoTDB与EdgeX Foundry集成适配服务介绍
  • RabbitMQ 开机启动配置教程
  • 前端判断内容文字是否溢出容器,创建临时元素来模拟文本实际宽度
  • JavaWeb:前后端分离开发-部门管理
  • 第四十二天打卡
  • [特殊字符] 革命性AI提示词优化平台正式开源!
  • sylar--线程模块
  • 电网“逆流”怎么办?如何实现分布式光伏发电全部自发自用?
  • 无监督学习-Complete Guide (较长)
  • yum更换阿里云的镜像源
  • 十六、【前端强化篇】完善 TestCase 编辑器:支持 API 结构化定义与断言配置
  • 极客大挑战 2019 EasySQL 1(万能账号密码,SQL注入,HackBar)
  • c++ stl常用算法
  • Seata 分布式事务 XA 模式
  • iTunes 无法备份 iPhone:10 种解决方法
  • [Java 基础]对象,膜具倒出来的
  • Python训练第四十四天
  • Ubuntu24.04 交叉编译 aarch64 ffmpeg
  • 多分辨率 LCD 的 GUI 架构设计与实现
  • AI基础知识(LLM、prompt、rag、embedding、rerank、mcp、agent、多模态)
  • 【Qt开发】文件
  • 【Linux仓库】冯诺依曼体系结构与操作系统【进程·壹】