P3403 跳楼机 同余最短路
链接:https://www.luogu.com.cn/problem/P3403
题意:给出了三个数字,让我们找出可以由这三个数字组合合成的所有数字数量(在一定范围内)
思路:第一次遇到这种题。我们先将这三个数按从小到大排序;
分别表示为a,b,c;
那么(b mod a) (c mod a),肯定是a的剩余系;
什么是剩余系呢?其实就是余数;
假设这三个数为3 4 5;
那么a的余数有0 1 2,这三个数;
我们的任务就是求出某数K的余数是(0或1或2)的最小整数;
然后这些整数不断叠加a,直到大于这个范围;
那么在这个范围内所叠加到的所有数,就是本题答案。
于是,我们的任务就是找出最小整数,那么如何找出最小整数呢,我们可以通过建图,然后跑最短路的方式来得出。
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define INF 0x3f3f3f3f 4 #define N 1000010 5 using namespace std; 6 ll first[N],next[N],go[N],cost[N],tot; 7 ll dist[N],vis[N],h,x,y,z,ans; 8 inline void add_edge(ll u,ll v,ll w){ 9 next[++tot]=first[u]; 10 first[u]=tot; 11 go[tot]=v; 12 cost[tot]=w; 13 } 14 inline void spfa(){ 15 queue<ll>q; 16 memset(dist,INF,sizeof(dist)); 17 memset(vis,0,sizeof(vis)); 18 dist[0]=1;vis[0]=1; 19 q.push(0); 20 while(!q.empty()){ 21 ll u=q.front();q.pop(); 22 vis[u]=0; 23 for(ll e=first[u];e;e=next[e]){ 24 ll v=go[e],w=cost[e]; 25 if(dist[v]>dist[u]+w){ 26 dist[v]=dist[u]+w; 27 if(!vis[v]){ 28 q.push(v);vis[v]=1; 29 } 30 } 31 } 32 } 33 } 34 signed main() 35 { 36 scanf("%lld%lld%lld%lld",&h,&x,&y,&z); 37 if(x==1||y==1||z==1){printf("%d",h);return 0;}//可以直接到任何楼层 38 for(int i=0;i<=x-1;i++){ 39 add_edge(i,(i+y)%x,y); 40 add_edge(i,(i+z)%x,z); 41 } 42 spfa(); 43 for(int i=0;i<=x-1;i++){ 44 if(dist[i]<=h) ans+=(h-dist[i])/x+1;//统计答案 45 } 46 printf("%lld",ans); 47 return 0; 48 }