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

同余最短路

时间:2022-11-10 10:14:56浏览次数:66  
标签:10 idx int srwudi 短路 样例 同余 dis

跳楼机

题目背景

DJL 为了避免成为一只咸鱼,来找 srwudi 学习压代码的技巧。

题目描述

Srwudi 的家是一幢 \(h\) 层的摩天大楼。由于前来学习的蒟蒻越来越多,srwudi 改造了一个跳楼机,使得访客可以更方便的上楼。

经过改造,srwudi 的跳楼机可以采用以下四种方式移动:

  1. 向上移动 \(x\) 层;
  2. 向上移动 \(y\) 层;
  3. 向上移动 \(z\) 层;
  4. 回到第一层。

一个月黑风高的大中午,DJL 来到了 srwudi 的家,现在他在 srwudi 家的第一层,碰巧跳楼机也在第一层。DJL 想知道,他可以乘坐跳楼机前往的楼层数。

输入格式

第一行一个整数 \(h\),表示摩天大楼的层数。

第二行三个正整数,分别表示题目中的 \(x, y, z\)。

输出格式

一行一个整数,表示 DJL 可以到达的楼层数。

样例 #1

样例输入 #1

15
4 7 9

样例输出 #1

9

样例 #2

样例输入 #2

33333333333
99005 99002 100000

样例输出 #2

33302114671

提示

可以到达的楼层有:\(1,5,8,9,10,12,13,14,15\)。

\(1 \le h \le 2^{63}-1\),\(1 \le x,y,z \le 10^5\)。

题解:

\(\%\%\%Mr\)_\(Leceue\)
先考虑如何统计答案,如果我们知道一个数 \(num\) 是由 \(y,z\) 构成的,即 \(num=a*y+b*z\),那么如果加上 \(x\) ,它能到达的楼层数为 \((h-num)/x+1\) 其中 \(+1\) 是因为要统计不加 \(x\) 时的答案;

那么如果我们能找到这些数,再去统计不就好了吗,但是会有重复,而且数字太过庞大,无法完全跑出,那么考虑什么时候回重复计数,即当 \(num1=num2+ax\) ,此时 \(num1\) 的贡献已经被 \(num2\) 统计过,再观察两个数字,发现 \(num1 \% x=num2 \% x\) ,那么我们只要找到余数相同中最小值即可,余数共有 xx 种;

设计转移方程: 设 \(f[i]f[i]\) 指余数为 ii 时最小楼层数,那么转移有两种方式;

\(f[(i+y)\%x]=min(f[i]+y,f[(i+y)\%x])\)

\(f[(i+z)\%x]=min(f[i]+z,f[(i+y)\%x])\)

​ 我们可以用最短路来优化类似于点 \(i\) 与点 \((i+y)\%x\) 连边,代价为 \(y\) ;

std:

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const int N = 2e5+9;
ll H,ans;
int x,y,z;

int h[N],ver[N],w[N],ne[N],idx;

void add(int u,int v,int val)
{
	idx++,ver[idx]= v,ne[idx] = h[u],w[idx] = val,h[u] = idx;
}

queue<int>q;
bool inq[N];
ll dis[N];
void spfa()
{
	for(int i = 0;i < x;i++)dis[i] = LLONG_MAX+1;//2^64
	q.push(1),inq[1] = 1,dis[1] = 1;
	while(!q.empty())
	{
		int u = q.front();inq[u] = 0,q.pop();
		for(int i = h[u];~i;i = ne[i])
		{
			int v = ver[i];
			if(dis[v] > dis[u] + w[i])
			{
				dis[v] = dis[u] + w[i];
				if(!inq[v])q.push(v),inq[v] = 1;
			}
		}
	}
}

int main()
{
	scanf("%lld%d%d%d",&H,&x,&y,&z);
	if(x == 1 || y == 1 || z == 1)return printf("%lld",H),0;
	
	if(x > y)swap(x,y);
	if(x > z)swap(x,z);
	memset(h,-1,sizeof h);
	for(int i = 0;i < x;i++)
	{
		add(i,(i+y)%x,y);
		add(i,(i+z)%x,z);
	}
	
	spfa();
	
	for(int i = 0;i < x;i++)
		if(H >= dis[i])ans += (H-dis[i])/x+1;
	
	printf("%lld",ans);
	
	return 0;
}
//putin:
//9223372036854775807
//10 10 10
//putout:
//922337203685477581

标签:10,idx,int,srwudi,短路,样例,同余,dis
From: https://www.cnblogs.com/AC7-/p/16876136.html

相关文章

  • 最短路
    题目:题解:模板题#include<bits/stdc++.h>usingnamespacestd;intpos[105][105];intdis[105];intvis[105];intinf=0x3f3f3f3f;intn,m;voiddij(){memset(dis,inf,si......
  • 最短路问题杂谈
    感觉这类问题好多变形,记录一下,方便复习。P1522[USACO2.4]牛的旅行CowTours由于题目的N很小,且要求任意两点之间距离,很容易想到一下暴力做法:求出题目的联通块,记id[......
  • 朴素的dijkstra最短路径算法
    dijkstra算法适用于无负权图中求最短路径,时间复杂度为O(n^2+e),n为节点数,e为边数需要的数据:1.n行两列数组arr[n][2],第一列记录当前节点到出发点的最短距离,第二列记录当......
  • 算法导论(第24章 单源最短路径)
    目录问题描述最短路径的几个变体最短路径的最优子结构负权重的边环路最短路径的表示松弛操作最短路径和松弛操作的性质本章概要24.1\(Bellman-Ford\)算法24.2有向无环图......
  • 迪杰斯特拉算法——求解单源最短路径
    constintmaxv=1000;constintINF=MAX_INT;//邻接矩阵形式intn,G[maxv][maxv];intvisited[maxv]={false};//表示是否已加入集合S中,S是已经访问过的节点集合intd[maxv]......
  • Dijkstra最短路径算法
    概念是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过......
  • 【XSY4055】小K的疑惑(模拟最短路,值域并查集)
    题面小K的疑惑题解以下的数都是在\(b\)进制意义下讨论。默认\(n\geqb\),否则\(n<b\)可以特判答案为\(1\)。考虑DP,设\(d_r\)表示所有模\(n\)余\(r\)的正......
  • 最短路径
    对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点是源点,最后一个顶点是终点。关于最短路径主要有两种算法,迪杰斯特拉(Dijkst......
  • 【XSY2418】修路(最短路图,支配)
    首先可以\(O(m\logn)\)按题意把树建出来,显然这是一棵最短路图的生成树。那么询问\(u,v\)相当于在树上\((u,v)\)路径上找到深度最深的一点\(w\),满足最短路图中刨掉......
  • 【SCOI2007】k短路(A_)
    考虑用\(A^*\)维护这个东西,由于其它题解都讲得很清楚\(A^*\)的原理了,我就在这里说一下这题需要注意的地方。按照\(A^*\)的套路,我们要把估价函数设为当前点到\(b\)......