首页 > 其他分享 >1.同余最短路

1.同余最短路

时间:2024-01-17 09:45:29浏览次数:36  
标签:短路 同余类 复杂度 同余 bmod dis

省选模拟赛 T3 一小部分用到了同余最短路,发现这简单东西自己从来没学过,补一下。


\(n\) 个正整数,分别为 \(A_1,A_2,\cdots,A_n\),求 \([0,V]\) 中有多少个数可以被表示为 \(\sum\limits_{i=1}^{n} A_ix_i,x_i\in \mathbb{N}\)。

可以完全背包,但复杂度 \(O(nV)\),当 \(V\) 很大的时候复杂度直接上天,我们想要找到一种与 \(V\) 无关的算法。

发现如果 \(x\) 可达,那么 \(x+kA_1,k\in \mathbb{N}\) 都可达。也就是对于每个模 \(A_1\) 的同余类 \([x]\),记其中可达的最小值为 \(d_x\),则这个同余类中所有大于等于 \(d_x\) 的数都可达。

假设现在我们知道 \(d_x\),我们加入一个数 \(v\),相当于有对 \(y=(x+v)\bmod A_1\) 有一个转移 \(d_y=min(d_y,d_x+v)\),类似最短路的形式。所以我们对于 \(i\in [2,n],j\in [0,A_1)\) 都建一条边 \(j\to (j+A_i)\bmod A_1\),边权为 \(A_i\),再在这个图上跑最短路,得到的答案即为每个同余类中可达的最小的数。

这样点数为 \(A_1\),边数为 \(nA_1\),使用 dij 的话时间复杂度 \(O(nA_1+n\log (nA_1))\)。

但是其实最短路是不必要的,对于一个数 \(v\),在模 \(m\) 时像上面那样建边,会形成 \(\gcd(v,m)\) 个子环,更新只会在同一个子环中进行,在没有负环的时候更新肯定不会转满一整圈,所以只需要在这个环里转两圈就可以把所有可能的更新都进行完。

这样枚举 \(n-1\) 个数字,时间复杂度 \(O(nA_1)\)。

可以选择最小的数作为 \(A_1\) 来减小常数。

P3403 跳楼机 板子。

    memset(dis,63,sizeof(dis));
    for(int i=0;i<x;++i)
        add(i,(i+y)%x,y),add(i,(i+z)%x,z);
    q.push({1,1%x});dis[1%x]=1;
    while(!q.empty())
    {
        int x=q.top().second;q.pop();
        if(vis[x]) continue;vis[x]=true;
        for(int i=head[x];i;i=nxt[i])
        {
            int y=to[i];
            if(dis[y]>dis[x]+val[i])
                dis[y]=dis[x]+val[i],q.push({dis[y],y});
        }
    }
    for(int i=0;i<x;++i)
        if(dis[i]<=h) ans+=(h-dis[i])/x+1;
    memset(dis,63,sizeof(dis));dis[1%x]=1;
    for(int i=0,lim=__gcd(y,x);i<lim;++i)
    {
        for(int cnt=0,p=i;cnt<2;cnt+=p==i)
        {
            int q=(p+y)%x;
            dis[q]=min(dis[q],dis[p]+y);p=q;
        }
    }
    for(int i=0,lim=__gcd(z,x);i<lim;++i)
    {
        for(int cnt=0,p=i;cnt<2;cnt+=p==i)
        {
            int q=(p+z)%x;
            dis[q]=min(dis[q],dis[p]+z);p=q;
        }
    }
    for(int i=0;i<x;++i)
        if(dis[i]<=h) ans+=(h-dis[i])/x+1;

P8060 [POI2003] Sums 也是板子。

P2371 [国家集训队] 墨墨的等式 仍是板子。

P2662 牛场围栏 还是板子。

答案是 \(\max\{(\lfloor\dfrac{d_i}{A_1}\rfloor-1)A_1+i,0\}\)。

P9140 [THUPC 2023 初赛] 背包

贪心加同余最短路。特殊的数据范围保证了 \(V\) 的下界,所以贪心的以性价比最高的为基准物品,跑同余最短路。转移时 \(d_y=\max(d_y,d_x+c_i-\lfloor\dfrac{x+v_i}{v_1}\rfloor c_1)\)。答案是 \(d_{V\bmod v_1}+\lfloor\dfrac{V}{v_1}\rfloor c_1\)。

[ABC077D] Small Multiple

不太常规,记 \(d_x\) 为模 \(k\) 的同余类 \([x]\) 中最小的数位累加和,对于 \(i\in [0,k)\) 分别建 \((i,(i+1)\bmod k,1)\) 和 \((i,(i*10)\bmod k,0)\) 的边,分别表示最后一位加一和扩大十倍,这样可以构造出所有数字。初始使 \(d_1=1\),答案为 \(d_0\)。

[ARC112F] Die Siedler

人类智慧转化一下。推个式子,然后根号分治。根号分治里一半是简单同余最短路。

我就是为了这碗醋才包的这顿饺子。但是我懒得写这题题解了。


算法学习笔记(93): 同余最短路

同余最短路的转圈技巧

标签:短路,同余类,复杂度,同余,bmod,dis
From: https://www.cnblogs.com/int-R/p/17969120/tongyuzuiduanlu

相关文章

  • C++U6-02-最短路算法1-dijkstra迪杰斯特拉最短路径
    学习目标 最短路径的基本概念  练习1 最短路的定义 本节课迪杰斯特拉dijkstra最短路算法 算法流程:以下是Dijkstra最短路径算法的逐步计算松弛的过程:初始化起始节点的距离为0,其他节点的距离为无穷大。选择当前距离最小且未被访问的节点作为当前节点。......
  • 图论 - 最短路随记
    顺序有点乱,后续会排一下,然后分板块整理All最短路算法的选择:\(n\le100\):Floyd(一般是较难的图论建模)\(n\le4\times10^5\):dijkstra尽量不用SPFA。神秘IDEA:一个带负权图,绝对最短路定义为,绝对值最小的最短路,求\(s\tot\)的绝对最短路。最短路中,任意......
  • 图论总结——最短路
    https://csacademy.com/app/graph_editor/https://riverhamster.gitee.io/app/graph_editor/注:时间复杂度分析中,假设\(n\lem\len^2\)。最短路本质上是一种DP。阶段:点状态:拆点决策:边最优子结构:最短路的任何子路径都一定是最短路。无后效性:正权图中一定可以找到一......
  • 【SPFA】最短路的一种算法
    SPFA算法是在bellman-ford算法基础上优化而来,所以我们先讨论bellman-ford算法bellman-ford算法的核心是‘松弛’。那么什么是松弛呢?以下图为例:假设数组d[i]表示源点s到达结点i的最短路径长度,那么松弛指的就是当d[a]+w<d[b],也就是说,这时候通过a到达b比原来的路径更......
  • P4021 [CTSC2012] 最短路
    [CTSC2012]最短路LuoguP4021题目描述给定一个节点\(1\)和节点\(n\)连通的正权无向图\(G\),请你删除不超过\(k\)条边,使得节点\(1\)和节点\(n\)仍然连通的同时,且这两点之间的最短路尽可能长。提交答案题。Solution模拟赛考到这道,改完这道题我爆了。提交答案题一......
  • Bellman-Ford算法实现带有负权边的单源最短路
    Bellman-Ford算法对于Dijkstra算法,不妨给出这样一个例子graphLRA((A))-->|1|C((C))A-->|2|D((D))D-->|-4|C根据Dijkstra算法的流程,选取A为源点。更新与A邻接的顶点,有C和D。选取已更新顶点中距离A的最小值,显然选择边权为1的边所连接的顶点C,并将C收入最短路集合S中,此......
  • G. Bicycles 分层图单源最短路
    题目链接简单描述一下题意:给定n个点,m条带权无向边,每个点i有一辆速度系数为Si的自行车。每经过一个点即可拥有该点的自行车,在任意两点之间路过的消耗为:已经拥有的某辆自行车的速度Si*边权Wi,求从1号点到n号点的最小消耗。思路:因为需要求的是最小的总消耗,所以在某个点出发时,我......
  • Dijkstra实现单源最短路
    Dijkstra算法求单源最短路Dijkstra算法应用于求一个给定图的单个源点到其他各顶点的最短路。其中应用Dijkstra算法的图应满足如下条件图中没有负权边有向或者无向图都可以图中若有自环或者重边也可以(需要自己先筛选一下)Dijkstra算法的核心就是从源点开始对各个顶点进行......
  • 洛谷B3647 【模板】Floyd 题解 floyd算法 求 多源多汇最短路
    题目链接:https://www.luogu.com.cn/problem/B3647floyd算法:https://oi-wiki.org/graph/shortest-path/#floyd-算法示例程序:#include<bits/stdc++.h>usingnamespacestd;constintmaxn=101;intn,m,f[maxn][maxn];intmain(){scanf("%d%d",&n......
  • P1339 [USACO09OCT] Heat Wave G 最短路入门题 Dijkstra/SPFA/Dijkstra+优先队列优化
    目录朴素的Dijkstra算法SPFA算法Dijkstra+优先队列优化题目链接:https://www.luogu.com.cn/problem/P1339题目大意:无向图有单源最短路。朴素的Dijkstra算法时间复杂度\(O(n^2)\)。#include<bits/stdc++.h>usingnamespacestd;constintmaxn=2505;structEdge......