题解 P3403 【跳楼机】
题解(瞎吹)
如果不考虑
因为
最终上升到的楼层和操作的顺序没有关系,所以我们可以将一种操作堆积起来,将一个到达的楼层分解为:
首先我们用最短路的方式求出数组
其中
翻译成人话就是用前两种操作到达一个高度h,这个高度和z取模的结果是i,
求出这个
那么这个答案是否有遗漏呢,假设我们从
所以这个楼层
这样的计算是不会用重复的。简单的证明(乱搞)如下:
使用反证法,如果同一个楼层能使用两种不同的方式得到,如果
两个多项式相等,则这两多项式最高次数相同,且对应次数项的系数相同.
那么得到
显然两个方法其实是同一个。
如果
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 1e5 + 5;
struct Edge {
int v, nex; LL w;
Edge(int v = 0, LL w = 0, int nex = 0) : v(v), w(w), nex(nex) {}
} E[maxn << 2];
int head[maxn], tote;
void addEdge(int u, int v, LL w) {
E[++tote] = Edge(v, w, head[u]), head[u] = tote;
}
LL h, x, y, z;
bool vis[maxn];
LL f[maxn];
queue<int> q;
int main() {
memset(f, 0x3f, sizeof(f));
memset(head, -1, sizeof(head));
// freopen("testdata.in", "r", stdin);
// freopen("testdata.out", "w", stdout);
scanf("%lld%lld%lld%lld", &h, &x, &y, &z);
for (int i = 0; i < x; i++)
addEdge(i, (i + y) % x, y),
addEdge(i, (i + z) % x, z);
q.push(1 % x), f[1 % x] = 1;
while (!q.empty()) {
int u = q.front(); q.pop(), vis[u] = false;
for (int i = head[u]; ~i; i = E[i].nex) {
int v = E[i].v;
if (f[v] > f[u] + E[i].w) {
f[v] = f[u] + E[i].w;
if (!vis[v]) vis[v] = true, q.push(v);
}
}
}
LL ans = 0;
for (int i = 0; i < x; i++)
if (f[i] <= h) ans += (h - f[i]) / x + 1;
printf("%lld\n", ans);
return 0;
}