跳楼机
从来没见过同余最短路,确实有点意思的。此类题关键在于,其中某个元素的范围很小,我们需要以此为切入点解决。方便起见,我们从
对于任何一个能到达的数,可以继续乘坐跳楼机上升
假设我们已经求出了仅使用
但是,一个数可能会被重复统计。这是由于
现在,对于每个
我们建立一个
从
确实很聪明的转化。
#include <bits/extc++.h>
using namespace std;
namespace pbds = __gnu_pbds;
istream& fin = cin;
ostream& fout = cout;
using ui = unsigned int;
using uli = unsigned long long int;
using li = long long int;
vector<uli> dijkstra(size_t s, vector<vector<pair<size_t, uli>>> const& mp) {
vector<uli> dis(mp.size(), numeric_limits<uli>::max() / 2);
vector<bool> vis(mp.size());
priority_queue<pair<uli, size_t>, vector<pair<uli, size_t>>,
greater<pair<uli, size_t>>>
q;
dis[s] = 0;
q.emplace(0, s);
while (!q.empty()) {
size_t p = q.top().second;
q.pop();
if (vis[p]) continue;
vis[p] = true;
for (auto i : mp[p])
if (dis[p] + i.second < dis[i.first])
q.emplace(dis[i.first] = dis[p] + i.second, i.first);
}
return dis;
}
int main(void) {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
uli h;
ui x, y, z;
fin >> h >> x >> y >> z;
--h;
vector<vector<pair<size_t, uli>>> mp(x);
for (size_t i = 0; i < x; ++i)
mp[i].emplace_back((i + y) % x, y), mp[i].emplace_back((i + z) % x, z);
auto dis = dijkstra(0, mp);
uli ans = 0;
for (size_t i = 0; i < x; ++i)
if (dis[i] <= h) ans += (h - dis[i]) / x + 1;
fout << ans;
return 0;
}