关于同余最短路
同余最短路可以解决形如「给定 个整数,求这 个整数能拼凑出多少的其他整数(可以重复取整数)」「给定 个整数,求这 个整数不能拼凑出的最小(最大)的整数」的问题 .
1. 跳楼机
给定 ,问有多少个 使得 ,其中 是变量 .
不妨设 .
令 表示最小的满足条件且 的 .
考虑将 加一(将 加一对 没有贡献),可以发现:
发现这与最短路中的 类似,所以对于每个 建一个点,将 连一条边权为 的边,将 连一条边权为 的边,然后跑一边最短路即可求出所有 .
不难发现,对于 ,每个 其答案的贡献为 ( 是因为自己也算一个),从而,答案为:
时间复杂度 (当然这里是 前提下的,一般的,时间复杂度是 )
Code:
using namespace std;
const int N=1e5+500;
typedef unsigned long long ull;
typedef long long ll;
ll x,y,z,h,dis[N];
bool vis[N];
typedef vector<pair<ll,ll> > graph[N];
graph g;
inline void addedge(ll u,ll v,ll w){g[u].push_back(make_pair(v,w));}
struct node
{
int idx; ll dis;
node(int _=0,ll __=0){idx=_; dis=__;}
bool operator <(const node& u)const{return dis>u.dis;}
};
void dijkstra(int s) // spfa 爬,dijkstra 天下第一
{
memset(dis,0x3f,sizeof dis); memset(vis,false,sizeof vis);
priority_queue<node> q; q.push(node(s,0)); dis[s]=0;
while (!q.empty())
{
node now=q.top(); q.pop(); int u=now.idx,S=g[u].size();
if (vis[u]) continue;
vis[u]=true;
for (int i=0;i<S;i++)
{
int v=g[u][i].first,w=g[u][i].second;
if (dis[u]+w<dis[v]){dis[v]=dis[u]+w; if (!vis[v]) q.push(node(v,dis[v]));}
}
}
}
int main()
{
scanf("%lld%lld%lld%lld",&h,&x,&y,&z);
if ((x==1)||(y==1)||(z==1)){printf("%lld",h); return 0;} // 假设 x<y<z,若 x=1,则令 q=r=0,从而 k 可以取到 [1,h] 中所有数
if (x>y) swap(x,y); // 这六句仅仅是为了让 x<y<z
if (y>z) swap(y,z);
if (x>z) swap(x,z);
if (x>y) swap(x,y);
if (y>z) swap(y,z);
if (x>z) swap(x,z);
for (int i=0;i<x;i++) addedge(i,(i+y)%x,y),addedge(i,(i+z)%x,z);
dijkstra(0); ll ans=0;
for (int i=0;i<x;i++)
if (h>=dis[i]) ans+=(h-dis[i]-1)/x+1; // 注意这里初始楼层是 1 所以每个 d[i] 都要 +1
printf("%lld",ans);
return 0;
}
仅在此题给出代码 .
2. 墨墨的等式
给定 ,问有多少个 使得 ,其中 是变量 .
上一题的拓展,上一题是 的特殊情况,这个一般的情况类似 .
时间复杂度
3. 很多序列
给定 个递增正整数 ,求不能由这些数字线性组合表示出的最大正整数 .
,,,, .
如果 ,那么就是小凯的疑惑,答案就是 .
类似的,把 向 连边权为 的边,跑一边最短路,假设最短路是 答案就是
4. 牛场围栏
给定序列 ,每个 可以减少至多 ,问无法表示为 的线性组合的最大数 .
和上一题类似 .
5. 货币系统
问题 的拓展,两种货币系统等价,当且仅当两种货币系统的 数组完全相同,开一个新数组记录转移用到的币值,并且要求币值尽量小 .
最后统计一下币值数目即可 .
6. 巡回
给定一个 个点 条边的无向图,问有没有 到 长度为 的路径 .
,,
任选一条边 ,注意到,如果有一条长度为 的路径,也必然会有长度为 的路径,故考虑在 意义下做同余最短路 .
令 表示满足存在一条从 到 长度为 的路径且 的最小的 ,转移用最短路算法实现即可 .
答案就是 .
注意若不存在从 到 的路径,那么也是不存在这样的路径的 .
以下是博客签名,正文无关
本文来自博客园,作者:yspm,转载请注明原文链接:https://www.cnblogs.com/CDOI-24374/p/14436668.html
版权声明:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0)进行许可。看完如果觉得有用请点个赞吧 QwQ
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】