「学习笔记」同余最短路
同余最短路,可以用来解决像“给定 个整数,求这 个整数能拼凑出多少的其他整数( 个整数可以重复取),以及给定 个整数,求这 个整数不能拼凑出的最小(最大)的整数,或者至少要拼几次才能拼出模 余 的数”的问题。
同于最短路是利用同余来构造状态,状态转移通常为 ,类似于 。
有 个数,分别为 ,算出这 个数最大的不能拼出的数,
某凯的疑惑?
只能说很像,但不完全是,毕竟这有 个数,某凯的疑惑是两个数。
这里,我们就可以用同余最短路来做了,首先,取出 来作为我们的模数 ,对于一个余数 ,会有一个数 ,使得 可以被拼出而 不能被拼出,那么,对于 来说, 就是最大的不能被拼出的数,对于每一个余数,我们会发现,都有一个 可以满足这样的关系( 可能为负数),因此我们只需要找出这些数中最大的数即可。具体如何操作,看代码。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, int> pil;
#define fir first
#define sec second
const int N = 1e7 + 5;
int n, m, seed, mod;
int a[N];
ll dis[N];
bool vis[N];
void dijkstra() {
priority_queue<pil, vector<pil>, greater<pil>> q;
for (int i = 0; i <= mod; ++ i) {
dis[i] = 1e18;
}
q.push({0, 0});
dis[0] = 0;
while (!q.empty()) {
pil it = q.top();
q.pop();
int u = it.second;
if (dis[u] != it.first) continue;
for (int i = 1; i <= n; ++ i) {
int v = (u + a[i]) % mod;
if (dis[v] > dis[u] + a[i]) {
dis[v] = dis[u] + a[i]; // 找到最小的能被拼出的数
q.push({dis[v], v});
}
}
}
}
int main() {
scanf("%d%d%d", &n, &m, &seed);
mt19937 rng(seed);
auto get = [&]() {
uniform_int_distribution<int> qwq(2, m);
return qwq(rng);
};
mod = m;
for (int i = 1; i <= n; i++) {
a[i] = get();
mod = min(mod, a[i]);
}
dijkstra();
ll ans = -1;
for (int i = 0; i < mod; ++ i) {
ans = max(ans, dis[i] - mod);
// dis 中存的是最小的能被拼出的数
//所以只要再 -mod,就是最大的不能拼出的数
}
printf("%lld\n", ans);
return 0;
}
作者:yifan0305
出处:https://www.cnblogs.com/yifan0305/p/17299790.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
转载时还请标明出处哟!
朝气蓬勃 后生可畏
Buy me a cup of coffee ☕.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】