【同余最短路】学习笔记

news/2025/10/24 19:26:16/文章来源:https://www.cnblogs.com/cold-jelly/p/19164094

例题 \(1\):P3403 跳楼机:给定正整数 \(h,x,y,z\),求有多少 \(d\in[1,h]\) 满足 \(ax+by+cz=d-1\),其中 \(a,b,c\) 为非负整数。

这道题第一眼给我的印象是一道数论题,但仔细想了想发现做不了。注意到 \(x,y,z\) 的范围较小,尝试从这个条件入手。

为方便起见,不妨将 \(h\)\(1\),那么初始楼层变为第 \(0\) 层,\(d\) 的范围改为 \([0,h-1]\)

注意到如果设 \(\mu=by+cz\),那么 \(\lambda x+\mu\)\(\lambda\in\mathbf{N}\))一定能够通过跳楼机到达。

因此我们考虑这样一个函数 \(f(i)\),其表示跳若干次 \(y\)\(z\) 后到达满足层数模 \(x\) 等于 \(i\) 的最小楼层,更数学一点表述就是 \(f(i)\) 等于满足 \((by+cz)\bmod x=i\) 的最小的 \(by+cz\)。根据定义,我们可以得出 \(f(i)\) 的两条性质:\(f(i)+y\ge f((i+y)\bmod x),f(i)+z\ge f((i+z)\bmod x)\)

这使我们联想到最短路中的 \(dist\) 函数。对于一张我们跑完一遍 Dijkstra 算法后的图,其每条边 \((u,v,w)\) 都应满足 \(dist(u)+w\ge dist(v)\)。这个式子的形式与上面的 \(f\) 函数是一致的。

因此我们可以考虑建图,按照对应关系,我们建一张包含 \(x\) 个点的有向带权图,点的编号为 \(0\sim x-1\),对于每个 \(i\in[0,x-1]\),我们建立有向边 \((i,(i+y)\bmod x,y)\)\((i,(i+z)\bmod x,z)\)

建完图后,跑一遍 Dijkstra 求得 \(dist\),这里的 \(dist\) 实际上就是上文的 \(f\) 函数。

那么对于每个点 \(i\),其对答案的贡献即为 \(\left\lfloor \dfrac{h-dist(i)}{x} \right\rfloor+1\)。所以答案即为 \(\displaystyle \sum^{x-1}_{i=0}\left\lfloor \dfrac{h-dist(i)}{x} \right\rfloor+1\)

代码实现如下:

#include<bits/stdc++.h>
#define int long long
#define PII pair<int, int>using namespace std;const int N = 1e5 + 10, INF = LLONG_MAX;int h, x, y, z, ans = 0;
vector<PII> e[N];int dist[N];
bool st[N];void dijkstra(int s)
{priority_queue<PII> q;for(int i = 0; i < N; i ++){dist[i] = INF;}dist[s] = 0;q.push({0, s});while(q.size()){int u = q.top().second;q.pop();if(st[u]){continue;}st[u] = true;for(auto i : e[u]){int v = i.second, w = i.first;if(dist[v] > dist[u] + w){dist[v] = dist[u] + w;q.push({-dist[v], v});}}}
}signed main()
{cin >> h >> x >> y >> z;h --;for(int i = 0; i < x; i ++){e[i].push_back({y, (i + y) % x});e[i].push_back({z, (i + z) % x});}dijkstra(0);for(int i = 0; i < x; i ++){if(h >= dist[i]){ans += (h - dist[i]) / x + 1;}}cout << ans;return 0;
}

例题 \(2\):P2371 [国家集训队] 墨墨的等式。

本题其实只是把上一题的 \(3\) 个数改为了 \(n\) 个,所以建图方式是一致的。

在统计答案时,考虑前缀和的思想,单点贡献为从 \(r\) 中扣掉 \(l-1\) 的部分。

注意 \(a_i=0\) 的数据要去掉。

#include<bits/stdc++.h>
#define int long long
#define PII pair<int, int>using namespace std;const int N = 5e5 + 10, M = 20, INF = LLONG_MAX;int n, m, mi = INF, id, ans = 0;
int l, r;
int a[M];
vector<PII> e[N];int dist[N];
bool st[N];void dijkstra(int s)
{priority_queue<PII> q;for(int i = 0; i < N; i ++){dist[i] = INF;}dist[s] = 0;q.push({0, s});while(q.size()){int u = q.top().second;q.pop();if(st[u]){continue;}st[u] = true;for(auto i : e[u]){int v = i.second, w = i.first;if(dist[v] > dist[u] + w){dist[v] = dist[u] + w;q.push({-dist[v], v});}}}
}signed main()
{cin >> n >> l >> r;l --;for(int i = 1; i <= n; i ++){int x;scanf("%lld", &x);if(x){a[++ m] = x;if(mi > x){mi = x;id = m;}}}for(int i = 0; i < mi; i ++){for(int j = 1; j <= m; j ++){if(j == id){continue;}e[i].push_back({a[j], (i + a[j]) % mi});}}dijkstra(0);for(int i = 0; i < mi; i ++){if(r >= dist[i]){ans += (r - dist[i]) / mi + 1;}if(l >= dist[i]){ans -= (l - dist[i]) / mi + 1;}}cout << ans;return 0;
}

例题 \(3\):Small Multiple:给定正整数 \(K\),求 \(K\) 的所有倍数的最小数位和。

每一个正整数都可以由 \(1\) 出发,仅经过若干次两种变换得到:

  1. 把数 \(+1\)
  2. 把数 \(\times 10\)

因为两种操作保证了可以任意决定数字的位数与每位上的数字是什么。

那么我们可以用每个数字代表一个点,点与点之间的连边表示两种操作。因为只有操作一会对数位和产生 \(1\) 的贡献,因此可以根据两种操作的类型给边权赋为 \(1/0\)。但这样做会有点小问题,如果对于每个数都建一个点空间不够,解决方案是由于同余,所以我们只需要开 \(0\sim K-1\)\(K\) 个点即可。那么初始点为 \(1\),我们要到达的 \(K\) 的倍数对应的点为 \(0\)

由于边权仅有 \(0\)\(1\),因此我们只需要跑一个 01BFS 即可。

#include<bits/stdc++.h>
#define PII pair<int, int>using namespace std;const int N = 1e5 + 10, INF = 1e9;int K;
vector<PII> e[N];int dist[N];
bool st[N];void bfs(int s)
{deque<int> q;for(int i = 0; i < N; i ++){dist[i] = INF;}dist[s] = 1;q.push_back(s);while(q.size()){int u = q.front();q.pop_front();if(st[u]){continue;}st[u] = true;for(auto i : e[u]){int v = i.second, w = i.first;if(dist[v] > dist[u] + w){dist[v] = dist[u] + w;if(st[v] == false){if(w){q.push_back(v);}else{q.push_front(v);}}}}}
}int main()
{cin >> K;for(int i = 0; i < K; i ++){e[i].push_back({1, (i + 1) % K});e[i].push_back({0, (i * 10) % K});}bfs(1);cout << dist[0];return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/945622.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ESP32-S3入门第七天:UART串口通信与设备交互 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

数字人:数字人公司深度解析与未来展望

数字人企业 数字人企业新趋势:虚拟与现实的融合探索 数字人企业深度解析与未来展望 在当今科技飞速发展的时代,数字人企业正成为推动创新与变革的重要力量。数字人,作为虚拟与现实交互的桥梁,不仅改变了人机交互的…

CSP/NOIP 复习:单调栈

最近模拟赛打的都不是太好,先随便复习复习吧,马上就要 CSPS 了,我可以考好的。 这里放一些单调栈的题目,笛卡尔树先不说,这个我已经忘了,后天复习一下。 本体 栈中维护有单调性的数据,入栈时维护这个单调性,这…

数字人企业:数字人公司排行榜深度解析

数字人企业新纪元:创新科技重塑未来生态 探秘数字人企业的核心驱动力与市场前景 数字人企业排行榜深度解析与趋势洞察 正文: 在数字化浪潮席卷全球的今天,数字人企业正成为科技领域的一颗新星,推动着虚拟与现实的深…

数字人公司:数字人新趋势技术驱动与市场前景解析

数字人企业 数字人企业新趋势:技术驱动与市场前景解析 数字人企业排行榜与深度点评 在当今科技飞速发展的时代,数字人企业正成为人工智能和虚拟交互领域的热门焦点。这些企业通过创新技术,推动着虚拟数字人在娱乐、…

算法分析--生成排列

排列简介全排列,有顺序要求。 递归实现如何实现查找第u位置有哪些数字可以用,选择查到的第一个,填上去。if(u > n){for(int i=1;i<=n;i++)cout<<path[i]<<" ";cout<<endl; }再去…

三大安全认证授权协议深度对比:OAuth、OpenID Connect与SAML

本文深入解析OAuth、OpenID Connect和SAML三大主流安全认证协议的技术原理、架构差异与应用场景,帮助开发者在Web应用中实现安全可靠的身份验证与授权机制,涵盖协议流程、安全机制对比及最佳实践建议。安全认证与授权…

数据绑定相关概念理解

中文译本将 Data Binding 译为了数据绑定,很大程度上其实是拼音音译,没有实际意义。WPF 中的Binding 更多地是表达一种桥梁关系。Binding 对象的两端,分别是源(Source)和目标(Target),源即数据来源,目标就是数据要…

数字人企业:数字人公司排行榜Top 3解析

数字人企业:探索行业创新与未来趋势 数字人企业的崛起与发展洞察 数字人企业排行榜Top 3解析 在数字人领域,众多企业凭借技术实力和市场表现脱颖而出。根据综合评估,以下是当前表现突出的三家数字人企业,优先以像衍…

WPF 深入系列.2.布局环境.布局控件.Grid

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

(简记)(自用)线段树区间拆分时间复杂度证明

如题,假定整数域线段树初始区间 \([1,n]\),每次划分长度不为 \(1\) 的区间 \([l,r]\) 会找到 \(mid=\lfloor\frac{l+r}{2}\rfloor\),划分成 \([l,mid],[mid+1,r]\)。求证划分任意合法区间 \([L,R]\) 最多使用 \(O(\…

冬日绘板 2026 珂朵莉计划 如何获取 Token

冬日绘板是全国 OIer 的一项社交活动,一般于每年元旦春节进行,主要博弈目标为获取更多的 tokens。形式类似于曾经的 bilibili 夏日绘板,游玩例子见 2024冬日绘版回忆录——听取MLE声一片。 冬日绘板 2026 珂朵莉计划…

数字人企业:数字人公司技术驱动的三大标杆

数字人企业:AI浪潮下的产业新势力 从技术突破到商业落地,数字人企业如何重塑行业生态 像衍科技领衔,数字人企业开启三维交互新纪元 一、数字人企业排行榜:技术驱动的三大标杆 在AI技术加速迭代的背景下,数字人企业…

Linux下的拼音输入法 (2)

此贴介绍sunpinyin. 它的用户词典是~/.sunpinyin/userdict,下面的程序往里面加词:// -I/usr/include/sunpinyin-2.0 add-word.cpp -lsunpinyin#include <ime-core/userdict.h> #include <pinyin/pinyin_dat…

数字人:怎么选择数字人实力公司

数字人企业哪家好?解锁未来科技新势力 2025数字人企业竞争力解析与行业领跑者揭秘 数字人企业技术生态图谱:从创新到落地的全链路观察 第一:数字人企业排行榜——2025年度三大标杆企业解析 数字人技术的爆发式增长,…

拉格朗日插值优化DP

拉格朗日插值优化DP 第一类:减少范围 发现答案是个 \(k\) 次多项式,即使值域很大,也可以直接通过前 \(k+1\) 项的值得到答案 例题一:P5469 NOI2019] 机器人 设 \(f_{l,r,i}\) 表示考虑区间 \([l,r]\),其最大值为 …

容斥练习笔记

某模拟赛题 对于任意 \(1\le k\le n\),若有 \(v_k\) 个长度为 \(n\) 的错位排列中存在长度为 \(k\) 的循环节,即对于 \(p_{1\cdots k-1}\),\(a_{p_i}=p_{i+1},a_{p_k}=p_1\)。求 \(\sum v\)。 首先考虑错排的限制,…

SpringBoot整合缓存2-Redis

一、是什么:缓存的基本概念 缓存是一种存储技术,用于临时保存频繁访问的数据,以减少对数据库的直接访问,从而提升系统响应速度和降低数据库压力。在本案例中,我们使用 Redis 作为缓存中间件,结合 SpringBoot 和 …

数字人企业:推荐数字人TOP3公司

数字人企业:技术浪潮中的新势力崛起 解码数字人企业核心赛道,看头部玩家如何重塑产业格局 从概念到落地,数字人企业如何撬动千亿级市场? 数字人企业排行榜:技术、资本与生态的三重博弈 在数字人产业蓬勃发展的当下…

数字人平台:重点推荐优质数字人公司

数字人企业:未来产业的新势力崛起 数字人企业技术赛道解析与头部玩家前瞻 从技术到场景,数字人企业如何重塑产业生态? 一、数字人企业排行榜:技术实力与商业价值的双重验证 在人工智能与元宇宙浪潮的推动下,数字人…