首页 > 其他分享 >同余最短路学习笔记

同余最短路学习笔记

时间:2023-11-06 23:45:07浏览次数:35  
标签:head idx int 短路 笔记 ans 同余

今天讲课讲到了同余最短路。简单记一下,防止之后忘了这个坑。

同余最短路 in oiwiki

简介

同余最短路,可以用来处理问题:

1.「给定 n 个数,求这些数能拼出多少其他数(选数数量不限)」

2.「给 n 个数,求这些数不能拼出的最大 or 最小值」

3.「至少拼几次才能拼出模 k 余 x 的数」。

同余最短路可以通过同余来构造状态,类比差分约束的转换思路,利用同余构造的状态可以看做单源最短路中的点。同余最短路的转移通常是:\(f(i+x)=f(i)+x\),类似于普通最短路中的 \(f(v)=f(u)+d(u,v)\)。

例题1:P3403 跳楼机

首先考虑,如果我只用 \(y\) 和 \(z\) 拼新,即 \(ay+bz = k\),对于每一个 \(k\),在我以后处理的过程中,无论加多少个 \(x\),其唯一不变的是 \(k%x\) 的这个值。

所以考虑对于与余数为 \([0,x)\) 的数,我们实际上只需要保留最小的 \(ay+bz\),这样才能在后面加 \(x\) 的处理中获得更大的数。

因此考虑,点编号就是余数,不断的往上添加 \(y\) 和 \(z\),以 \([0,x)\) 为分别边的起点,以 \(f(i+x)=f(i)+x\) 作为转移,新的余数作为边的终点,加上的 \(y\),\(z\) 作为边权。

对其跑最短路,\(d_i\) 就是同余中的最小 \(k\)。

因为最大限制为 \(h\),那你从 \(k\) 通过 \(x\) 的倍数最多能翻出来 \(\left \lfloor{ \frac{h-k}{x}}\right \rfloor + 1\)(加一是考虑 \(x\) 的系数为 \(0\))。答案加起来。

嗯我 \(x\) 写成 \(t\) 是因为两个变量名重了。调了一阵子。感谢机房大佬帮我调。

特别注意当 \(x\) 为 \(1\) 时其模数没有意义,需要特判。

#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
const int N=2e5+10;
ll h,ans;
int t,y,z;
priority_queue<pair<ll,int> >q;
int idx,e[N],w[N],nxt[N],head[N];
int vis[N];
ll d[N];
void add(int x,int y,int z){
	e[++idx]=y;
	w[idx]=z;
	nxt[idx]=head[x];
	head[x]=idx;
}
void dij(){
	memset(d,0x3f,sizeof d);
	d[1%t]=1;
	q.push(make_pair(-1,1%t));
	while(q.size()){
		int x=q.top().second;
		q.pop();
		if(vis[x]) continue;
		vis[x]=1;
		for(int i=head[x];i;i=nxt[i]){
			if(d[e[i]]>d[x]+w[i]){
				d[e[i]]=d[x]+w[i];
				q.push(make_pair(-d[e[i]],e[i]));
			} 
		}
	}
}
int main(){
	scanf("%lld%d%d%d",&h,&t,&y,&z);
	for(int i=0;i<t;i++){
		add(i,(i+y)%t,y);
		add(i,(i+z)%t,z);
	}
	dij();
	for(int i=0;i<t;i++) if(h>=d[i]&&d[i]!=INF) ans+=((h-d[i])/t+1);
	printf("%lld",ans);
}

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

做法类比上一题,对于以一个数作为基准建边跑同余最短路,最后对于区间类似前缀和统计。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=5e6+10;
ll l,r,ans;
ll d[N];
int n;
int vis[N];
int idx,e[N],w[N],nxt[N],head[N];
priority_queue<pair<int,int> > q;
void add(int x,int y,int z){
	e[++idx]=y;
	w[idx]=z;
	nxt[idx]=head[x];
	head[x]=idx;
}
void dij(){
	memset(d,0x3f,sizeof d);
	d[0]=0;
	q.push(make_pair(0,0));
	while(q.size()){
		int x=q.top().second;
		q.pop();
		if(vis[x]) continue;
		vis[x]=1;
		for(int i=head[x];i;i=nxt[i]){
			if(d[e[i]]>d[x]+w[i]){
				d[e[i]]=d[x]+w[i];
				q.push(make_pair(-d[e[i]],e[i]));
			}
		}
	}
}
int main(){
	int x,y;
	scanf("%d%lld%lld%d",&n,&l,&r,&x);
	for(int i=1;i<n;i++){
		scanf("%d",&y);
		for(int i=0;i<x;i++) add(i,(i+y)%x,y); 
	}
	dij();
	l--;
	for(int i=0;i<x;i++){
		if(r>=d[i]) ans+=(r-d[i])/x+1;
		if(l>=d[i]) ans-=(l-d[i])/x+1;
	}
	printf("%lld",ans);
	return 0;
}

注意这个题,数组需要开 5e6。开大了会 MLE,小了会显示 TLE。别问我怎么知道的。

标签:head,idx,int,短路,笔记,ans,同余
From: https://www.cnblogs.com/Moyyer-suiy/p/17814080.html

相关文章

  • 【python爬虫】80页md笔记0基础到scrapy项目高手,第(4)篇:requests和网络数据获取进阶
    本阶段主要学习requests这个http模块,该模块主要用于发送请求响应,该模块有很多的替代模块,比如说urllib模块,但是在工作中用的最多的还是requests模块,requests的代码简洁易懂,相对于臃肿的urllib模块,使用requests编写的爬虫代码将会更少,而且实现某一功能将会简单。因此建议大家掌握该......
  • 【笔记】博弈论
    【笔记】博弈论0基本概念&性质0.1博弈论1SG函数ps.通过SG函数来理解三个基本模型,也是不错的选择。1.2定义\(\text{SG}(x)=\text{mex}\{\text{SG}(y_i)\}\)(其中\(y_i\)为\(x\)的后继状态)1.3SG定理由\(n\)个博弈图组成的游戏,设起点(即每个连通分量内入......
  • 多线程学习笔记
    **Process与Thread**说起进程,就不得不说下程序。程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。而进程则是执行程序的一次执行过程,它是一个动态的概念。是系统资源分配的单位。通常在一个进程中可以包含若干个**线程**,当然一个进程中至少有一个线程,不......
  • 学习笔记9
    一、学习任务自学教材第6章,提交学习笔记(10分),评分标准如下1.知识点归纳以及自己最有收获的内容,选择至少2个知识点利用chatgpt等工具进行苏格拉底挑战,并提交过程截图,提示过程参考下面内容(4分)“我在学***X知识点,请你以苏格拉底的方式对我进行提问,一次一个问题”核心是要求GPT:“......
  • 单调队列学习笔记
    Menu单调队列(MonotonicQueue)简介代码模板例题单调栈(MonotonicStack)简介代码模板例题......
  • 2023_11_06_Java_EE_DAY_01_笔记
    2023_11_06_Java_EE_DAY_01_笔记知识点回顾:JavaseMysqlHtml+css+javascriptVue扩展:ElementPlus作业讲解与分析:知识点讲解:1. 主要核心内容(服务器端开发)a) Javaee/Spring+springMVC+MyBatis/MyBatisPlus/SpringBoot等b) 全栈工程师2. 工具:a) Idea+Mavenb) 等3. ......
  • [学习笔记]虚树
    虚树虚树可以应用于树形\(DP\)的加速。当题目规定查询点集的大小和\(\le10^5\)时可以用虚树解决。虚树的原理是在原树上重新建一棵树,使得树上只包含要询问的点和它们的\(lca\)。普通树形\(DP\)的时间复杂度为\(O(n^2)\)。最坏形成一棵二叉树,点集大小为\(n\),总点数为......
  • 【Redis使用手册】一年多来redis使用markdow笔记总结,第(2)篇:Redis命令操作详解
    Redis是一个高性能的key-value数据库。本文会让你知道:什么是nosql、Redis的特点、如何修改常用Redis配置、写出Redis中string类型数据的增删改查操作命令、写出Redis中hash类型数据的增删改查相关命令、说出Redis中list保存的数据类型、使用StrictRedis对象对string类型数据......
  • ArSSR笔记
    20231105文章连接:https://arxiv.org/abs/2110.144761.提出背景首先是MRI成像上,会因为多种情况导致最后的成像效果不好,想要质量高的图像多徐时间又很长,现在采用超分的图像后处理方法来对图像进行处理以实现短时间获得高质量图像的效果。但是现在的图像超分方法中的SISR方法实现......
  • 算法--笔记--单调栈
    单调栈是为了解决两层foru循环O(n^2)变为O(n)的问题思路是:维持一个单调栈.依次进入单调栈,并淘汰对后续没有帮助的对象当一个对象从栈里弹出的时候,结算当前对象参与的答案。如何判断单调栈是大压小还是小压大呢?左侧的要小的,就是大压小左侧的要大的,就是小压大......