#同餘最短路#洛谷 3403 跳樓機
阿新 • • 發佈:2020-08-18
分析
如果\(x,y,z\)有一個是1答案肯定是大樓層數
首先回到第一層顯然是沒有用的,考慮bfs,顯然會TLE
但是在此過程中可以發現有很多冗餘狀態(比如說不斷加\(x\))
考慮以\(x\)為模數在這個同餘系中,
求出一個點\(y\)跳到這個點的最小層數\(dis=\min \{y+kx\}\)
如果\(dis<=n\)那麼就能產生\((n-dis)/x+1(它自己)\)的貢獻
顯然跳的過程可以用同餘最短路實現
程式碼
#include <cstdio> #include <cstring> #include <queue> #define rr register using namespace std; const int N=100011; typedef long long lll; struct node{int y,w,next;}e[N<<1]; queue<int>q; int X,Y,Z,as[N],k; lll n,dis[N],ans; bool v[N]; inline void add(int x,int y,int w){e[++k]=(node){y,w,as[x]}; as[x]=k;} signed main(){ memset(as,-1,sizeof(as)),memset(dis,0x3f,sizeof(dis)); scanf("%lld%d%d%d",&n,&X,&Y,&Z); if (X==1||Y==1||Z==1) return !printf("%lld",n); for (rr int i=0;i<X;++i) add(i,(i+Y)%X,Y),add(i,(i+Z)%X,Z); q.push(1),dis[1]=1,v[1]=1; while (q.size()){ rr int x=q.front(); q.pop(); for (rr int i=as[x];~i;i=e[i].next) if (dis[e[i].y]>dis[x]+e[i].w){ dis[e[i].y]=dis[x]+e[i].w; if (!v[e[i].y]) v[e[i].y]=1,q.push(e[i].y); } v[x]=0; } for (rr int i=0;i<X;++i) if (dis[i]<=n) ans+=(n-dis[i])/X+1; return !printf("%lld",ans); }