解题思路:
最短路构造很神啊。
先用前两个值跑在第三个值模意义下的同余最短路(这步贪心可以证明,如果第三步长为z,那么如果n+z可以达到,n+2z同样可以达到)
最后计算与楼顶差多少个模计算一下就好了(细节:不要忘了自己也是一个解)。
代码:
1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 typedef long long lnt; 6 struct pnt{ 7 int hd; 8 lnt dis; 9 int no; 10 bool vis; 11 bool friend operator < (pnt x,pnt y) 12 { 13 return x.dis>y.dis; 14 } 15 }p[1000000]; 16 /*class heap{ 17 public: 18 void push(pnt x) 19 { 20 ln[++siz]=x; 21 int nw=siz; 22 while((nw>>1)>=1) 23 { 24 int nx=nw>>1; 25 if(ln[nx].dis<=ln[nw].dis) 26 break; 27 std::swap(ln[nx],ln[nw]); 28 nw=nx; 29 } 30 return ; 31 } 32 void pop(void) 33 { 34 ln[1]=ln[siz--]; 35 int nw=1; 36 while((nw<<1)<=siz) 37 { 38 int nx=nw<<1; 39 if(ln[nx+1].dis<ln[nx].dis&&nx<siz) 40 nx++; 41 if(ln[nx].dis>=ln[nw].dis) 42 break; 43 std::swap(ln[nx],ln[nw]); 44 nw=nx; 45 } 46 return ; 47 } 48 int top(void) 49 { 50 return ln[1].no; 51 } 52 bool empty(void) 53 { 54 return (siz==0); 55 } 56 private: 57 pnt ln[1000000]; 58 int siz; 59 }Q;*/ 60 std::priority_queue<pnt>Q; 61 struct ent{ 62 int twd; 63 int lst; 64 lnt vls; 65 }e[1000000]; 66 lnt H; 67 int x,y,z; 68 int cnt; 69 lnt ans; 70 void ade(int f,int t,lnt v) 71 { 72 cnt++; 73 e[cnt].twd=t; 74 e[cnt].lst=p[f].hd; 75 e[cnt].vls=v; 76 p[f].hd=cnt; 77 return ; 78 } 79 void Init(void) 80 { 81 for(int i=0;i<=z;i++) 82 { 83 p[i].no=i; 84 p[i].dis=0x3f3f3f3f3f3f3f3fll; 85 } 86 p[1%z].dis=1; 87 return ; 88 } 89 void Dij(void) 90 { 91 Q.push(p[1%z]); 92 while(!Q.empty()) 93 { 94 int x=Q.top().no; 95 Q.pop(); 96 if(p[x].vis) 97 continue; 98 p[x].vis=true; 99 for(int i=p[x].hd;i;i=e[i].lst) 100 { 101 int to=e[i].twd; 102 if(p[to].dis>p[x].dis+e[i].vls) 103 { 104 p[to].dis=p[x].dis+e[i].vls; 105 Q.push(p[to]); 106 } 107 } 108 } 109 return ; 110 } 111 int main() 112 { 113 scanf("%lld%d%d%d",&H,&x,&y,&z); 114 Init(); 115 for(int i=0;i<z;i++) 116 { 117 ade(i,(i+x)%z,x); 118 ade(i,(i+y)%z,y); 119 } 120 Dij(); 121 for(int i=0;i<z;i++) 122 if(p[i].dis<=H) 123 ans+=((H-p[i].dis)/z+1); 124 printf("%lld ",ans); 125 return 0; 126 }