首页 > 其他分享 >[浅谈] 同余最短路

[浅谈] 同余最短路

时间:2023-05-05 15:59:03浏览次数:39  
标签:node 浅谈 int 短路 read while push 同余 dis

\(\color{red}\text{总述}\)

所谓同余最短路,就是把余数相同的情况归为一类,然后找到形成这种情况的最短路径。

\(\color{purple}\text{P3403 跳楼机}\)

我们假设只能跳 \(x\) 步。那么可以达到的楼层是 \(x,2x,3x,4x\) ,他们的共同点是 \(\%x=0\) 。

那么现在再加个可以跳 \(y\) 步(若 \(y\) 不是 \(x\) 的倍数且 \(y<x\)),那么我们可以跳到 \(x+y,2x+y,3x+y\) 等 \(\%x=y\) 的点。或许还有更多种类,因此我们可以把对 \(x\) 取余相同的数归为一类,找到这类数的最小数,那么这类数大于等于最小数的数都可以表示了。

我们可以把每类数看做一个点,假设目前点为 \(u\) ,那么我们跳 \(y\) 层时,相当于到了 \((u+y)%x\) 点,然后最小层数用权值求。我们便可以建一条边 \((u,(y+u)\%x,y)\)。

以此类推,建完所有边后,跑一边 \(djk\),那么每类数的最小值知道,有多少个就知道,答案就知道了。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+110;
int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9' || c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0' && c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
int h,x,y,z;
int dis[N],head[N],to[N*5],last[N*5],w[N*5],tot;
void add(int u,int v,int t){to[++tot]=v,w[tot]=t,last[tot]=head[u],head[u]=tot;return;}
struct node{
	int dis,u;
	bool operator<(const node A)const{return A.dis<dis;}
};
void dijkstra(){
	memset(dis,0x3f,sizeof(dis));dis[0]=0;
	priority_queue<node>q;q.push((node){0,0});
	while(!q.empty()){
		int u=q.top().u;q.pop();
		for(int i=head[u];i;i=last[i]){
			int v=to[i];
			if(dis[v]>dis[u]+w[i]){
				dis[v]=dis[u]+w[i];
				q.push((node){dis[v],v});
			}
		}
	}
	return;
}
signed main(){
	h=read()-1,x=read(),y=read(),z=read();
	for(int i=0;i<x;i++){
		add(i,(i+y)%x,y);
		add(i,(i+z)%x,z); 
	}
	dijkstra();int ans=0;
	for(int i=0;i<x;i++)if(h>=dis[i])ans+=(h-dis[i])/x+1;
	printf("%lld\n",ans);
	return 0;
} 

\(\color{purple}\text{P2371 [国家集训队]墨墨的等式}\)

把 \(x\) 看作跳的层数, \(b\) 看作最终跳到哪里,那么就与上题一样了。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+110;
int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9' || c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0' && c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
int n,l,r,a[N];
int dis[N],head[N],to[N*13],last[N*13],w[N*13],tot;
void add(int u,int v,int t){to[++tot]=v,w[tot]=t,last[tot]=head[u],head[u]=tot;return;}
struct node{
	int dis,u;
	bool operator<(const node A)const{return A.dis<dis;}
};
void dijkstra(){
	memset(dis,0x3f,sizeof(dis));dis[0]=0;
	priority_queue<node>q;q.push((node){0,0});
	while(!q.empty()){
		int u=q.top().u;q.pop();
		for(int i=head[u];i;i=last[i]){
			int v=to[i];
			if(dis[v]>dis[u]+w[i]){
				dis[v]=dis[u]+w[i];
				q.push((node){dis[v],v});
			}
		}
	}
	return;
}
signed main(){
	n=read(),l=read(),r=read();
	for(int i=1;i<=n;i++)a[i]=read();
	for(int i=0;i<a[1];i++){
		for(int j=2;j<=n;j++)
			add(i,(i+a[j])%a[1],a[j]);
	}
	dijkstra();int ans=0;
	for(int i=0;i<a[1];i++){
		if(r>=dis[i])ans+=(r-dis[i])/a[1]+1;
		if(l-1>=dis[i])ans-=(l-1-dis[i])/a[1]+1;
	}
	printf("%lld\n",ans);
	return 0;
} 

\(\color{purple}\text{P2662 牛场围栏}\)

还是按 \(x\) 的余数分类,求出没类数最小表示长度 \(len[i]\), 答案就是 \(\max(len[i]-x)\)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=3010;
int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9' || c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0' && c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
int n,m,k,bk[N],a[N];
int gcd(int a,int b){
	return b==0?a:gcd(b,a%b);
}
int dis[N],head[N],to[N*3000],last[N*3000],w[N*3000],tot;
void add(int u,int v,int t){to[++tot]=v,w[tot]=t,last[tot]=head[u],head[u]=tot;return;}
struct node{
	int dis,u;
	bool operator<(const node A)const{return A.dis<dis;}
};
void dijkstra(){
	memset(dis,0x3f,sizeof(dis));dis[0]=0;
	priority_queue<node>q;q.push((node){0,0});
	while(!q.empty()){
		int u=q.top().u;q.pop();
		for(int i=head[u];i;i=last[i]){
			int v=to[i];
			if(dis[v]>dis[u]+w[i]){
				dis[v]=dis[u]+w[i];
				q.push((node){dis[v],v});
			}
		}
	}
	return;
}
int main(){
	n=read(),m=read();
	for(int i=1;i<=n;i++){
		int t=read();
		for(int i=t;i>=max(1,t-m);i--)bk[i]=1;
	}
	for(int i=1;i<=3000;i++)
		if(bk[i])a[++k]=i;
	int t=a[1];
	for(int i=2;i<=k;i++)t=gcd(t,a[i]);
	if(t!=1 || a[1]==1){
		printf("-1\n");
		return 0;
	}
	for(int u=0;u<a[1];u++)
		for(int i=2;i<=k;i++)
			add(u,(u+a[i])%a[1],a[i]);
	dijkstra();int ans=0;
	for(int i=0;i<a[1];i++){
		ans=max(ans,dis[i]-a[1]);
	}
	printf("%d\n",ans);
	return 0;
}

\(\color{purple}\text{[ABC077D] Small Multiple}\)

把数按 \(\%K\) 的余数分类,权值为数位累加和,答案就是 \(\%k=0\) 的最小表示法。

  1. 如果把个位 \(+1\) ,余数加一(或归零),答案加一,建边 \((u,(u+1)\%K,1)\) 。
  2. 如果乘 \(10\), 答案不变,建边 \((u,(10u)\%K,0)\) 。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+110;
int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9' || c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0' && c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
int k;
int dis[N],head[N],to[N*3],last[N*3],w[N*3],tot;
void add(int u,int v,int t){to[++tot]=v,w[tot]=t,last[tot]=head[u],head[u]=tot;return;}
struct node{
	int dis,u;
	bool operator<(const node A)const{return A.dis<dis;}
};
void dijkstra(){
	dis[0]=2e9;
	for(int i=1;i<k;i++){
		int j=i;
		while(j)dis[i]+=j%10,j/=10;		
	}
	priority_queue<node>q;
	for(int i=1;i<k;i++)q.push((node){dis[i],i});
	while(!q.empty()){
		int u=q.top().u;q.pop();
		for(int i=head[u];i;i=last[i]){
			int v=to[i];
			if(dis[v]>dis[u]+w[i]){
				dis[v]=dis[u]+w[i];
				q.push((node){dis[v],v});
			}
		}
	}
	return;
}
int main(){
	k=read();
	for(int i=0;i<k;i++){
		add(i,(i+1)%k,1);
		add(i,(i*10)%k,0);
	}
	dijkstra();
	printf("%d\n",dis[0]);
	return 0;
}

标签:node,浅谈,int,短路,read,while,push,同余,dis
From: https://www.cnblogs.com/FJOI/p/17374353.html

相关文章

  • 浅谈地下污水厂智能照明控制应用
    罗轩志江苏安科瑞微电网研究院有限公司江苏江阴214432   摘要:结合某地下污水厂项目,从结构、系统组成、系统功能、控制要求、场景模式等方面介绍了地下污水厂智能照明控制系统,探索了一套适用于地下污水厂的智能照明控制策略,以确保地下污水厂正常运行的照明需求。  关键词:智......
  • 浅谈无线测温系统在煤矿高压电气设备上的应用
    罗轩志江苏安科瑞电器制造有限公司  江苏江阴  214405   摘要:随着社会经济的不断发展,电力系统向着高电压、高容量的方向前进着,电力系统全新的技术与设备层出不穷,电力的输送能力不断提升。然而,高压电气设备承载的高压电力负荷也让其自身的温升问题成为了威胁电网稳定的元凶,......
  • 浅谈智慧医院的信息集成平台建设与配电设计方案
    罗轩志江苏安科瑞微电网研究院有限公司 江苏江阴 214432  摘要:随着云计算、5G、大数据、物联网等技术的不断发展与进步,推动着智慧医院建设的飞速发展。智慧医院建设强调医院内部业务的多流程联动和医疗信息互联互通的高协同效率,突出了数据驱动下构建高质量数据的必要性。文章......
  • 浅谈中压系统母线弧光保护的必要性
     罗轩志江苏安科瑞微电网研究院有限公司  江苏江阴  214432   摘要:本文介绍了中低压开关柜内部发生电弧故障的原因、危害以及弧光保护在中压母线保护中的原理、用途、应用关键点,同时还介绍了弧光保护应用现状,探讨了无线测温在线监测系统在实际工作场景中的应用案例,证明了......
  • 浅谈电动汽车智能充电桩及运营管理云解决方案
    罗轩志江苏安科瑞电器制造有限公司  江苏江阴 214400  摘要:电动汽车采用了电力作为发动能源,但是同样存在很大缺陷,即续航能力方面存在较大不足。因此如何利用现代技术进行电动汽车的智能充电便十分重要。在电动汽车智能充电的研究过程中需要用到的技术有有电力电子变流技......
  • 浅谈新能源电动汽车充电设施的建设及运营平台分析
    罗轩志江苏安科瑞电器制造有限公司  江苏江阴 214400   摘要:在社会经济发展的新时期,我国城市化的水平也在随之不断的提高,使我国制造业迅速崛起,并加剧了该行业的竞争力,要想使企业在竞争中占据有力的位置,企业就要顺应时代发展的潮流,加强重视环境保护的理念,不断探寻出新能源电......
  • 浅谈智能照明控制系统在智慧建筑中的应用
     罗轩志江苏安科瑞电器制造有限公司  江苏江阴  214405   摘要:新时期,建筑行业发展迅速,在信息化背景下,建筑功能逐渐拓展,呈现了智能化的发展态势。智能建筑更加安全、节能、环保,也符合绿色建筑理念。在建筑智能化发展背景下,智能照明系统受到了各界的重视。智能照明系统具有......
  • 生成函数浅谈
    羊驼说,要当老师,所以强大的羊驼教会了我们生成函数。羊驼说,我们有卷积,所以生成函数的问题通常可以在带\(log\)的时间复杂度内解决这类问题。普通型生成函数数列\(1,1,1,1,1,1\)的普通型生成函数就是\(1+x+x^2+x^3+x^4+x^5\)。而数列\(1,1,\cdots,1,1,\cdots\)的普通型生......
  • 导数浅谈
    本文知识部分由AKauto和mashduihca倾情提供目录导数表及其证明导数运算法则及其证明练习题前言函数的导数是表示函数在某一点的切线斜率的函数。前置知识:\[\lim_{x\to\infty}e=(1+\frac{1}{x})^x\]\[\lim_{x\to0}\frac{\sinx}{x}=1\]导数表及其证明\(f(......
  • 浅谈如何使用 github.com/kardianos/service
    在实际开发过程中,有时候会遇到如何编写Go开机自启服务的需求,在linux中我们可以使用systemd来进行托管,windows下可以通过注册表来实现,mac下可以通过launchd来实现,上面的方式对于开发者来说,并不是什么困难的事情,但是对于使用者而言,是并不希望通过这么复杂的方式来达到开机自启的功能......