【luogu3403】跳楼机 [同余最短路]

P3403 跳楼机

P3403 跳楼机

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

向上移动x层;向上移动y层;向上移动z层;回到第一层。

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

yyb:先只考虑只用\(y,z\)两种移动方式,它们一定能够到达一些楼层,
那么这些楼层再只用\(x\)拓展就能够计算答案。
那么我们这样子计算答案,设\(dis[i]\)表示可以到达\(mod\ x=i\)楼层的最小值,

很巧妙!同余最短路

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=100000+10,M=100000+10,inf=0x3f3f3f3f;
int x,y,z;
ll n,ans=0;
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

int head[N],tot=0;
struct edge{int v,w,nxt;}e[M<<2];
void add(int u,int v,int w){
	e[++tot]=(edge){v,w,head[u]},head[u]=tot;
}

queue<int>q;bool vis[N];
ll dis[N];
void spfa(){
	memset(dis,inf,sizeof(dis));
	memset(vis,0,sizeof(vis));
	q.push(1),vis[1]=1,dis[1]=1;
	while(!q.empty()){
		int u=q.front();q.pop(),vis[u]=0;
		for(int i=head[u],v,w;i;i=e[i].nxt)
		if(dis[v=e[i].v]>dis[u]+(w=e[i].w)){
			dis[v]=dis[u]+w;
			if(!vis[v]) q.push(v),vis[v]=1;
		}
	}
}

int main(){
//	freopen("in.txt","r",stdin);
	rd(n),rd(x),rd(y),rd(z);
	if(n==1||x==1||y==1||z==1) return printf("%lld",n),0;
	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(dis[i]<=n) ans+=(n-dis[i])/x+1;
	printf("%lld",ans);
	return 0;
}

[国家集训队]墨墨的等式

和跳楼机那题是一样的==

#include<bits/stdc++.h>
using namespace std;
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
#define ll long long
const int N=12+10,M=500000+10,inf=0x3f3f3f3f;
int n,a[N];
ll b1,b2,ans=0;
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

int head[M],tot=0;
struct edge{int v,w,nxt;}e[M*20];
void add(int u,int v,int w){
	e[++tot]=(edge){v,w,head[u]},head[u]=tot;
}

queue<int>q;bool vis[M];
ll dis[M];
void spfa(){
	memset(dis,inf,sizeof(dis));
	memset(vis,0,sizeof(vis));
	q.push(0),vis[0]=1,dis[0]=0;
	while(!q.empty()){
		int u=q.front();q.pop(),vis[u]=0;
		for(int i=head[u],v,w;i;i=e[i].nxt)
		if(dis[v=e[i].v]>dis[u]+(w=e[i].w)){
			dis[v]=dis[u]+w;
			if(!vis[v]) q.push(v),vis[v]=1;
		}
	}
}

int main(){
	freopen("in.txt","r",stdin);
	rd(n),rd(b1),rd(b2);
	for(int i=1;i<=n;++i) rd(a[i]);
	sort(a+1,a+n+1);
	for(int i=0;i<a[1];++i)
		for(int j=2;j<=n;++j) add(i,(i+a[j])%a[1],a[j]);
	spfa();
	for(int i=0;i<a[1];++i){
		if(dis[i]<=b1-1) ans-=(b1-1-dis[i])/a[1]+1;
		if(dis[i]<=b2) ans+=(b2-dis[i])/a[1]+1;
	}
	printf("%lld",ans);
	return 0;
}
posted @ 2019-09-17 14:32  委屈的咸鱼鱼鱼鱼  阅读(148)  评论(0编辑  收藏  举报