同余最短路
类似的做法罢了。
P3403 跳楼机
题目概述
求满足 \(ax+by+cz+1\leq H\) 的个数,其中 \(x,y,z\) 给定,然后均 \(\leq 10^5,H\leq 10^9\)。
分析
移项,所以让 \(H-1\)。
注意到我们知道一个高度 \(h\) 其对 \(x\) 取模的最小值之后,那么可以通过这个算出这种模上 \(x\) 同余的方案,记这个最小值为 \(t\),那么答案就是 \(\left\lfloor\frac{(H-t)}{x}\right\rfloor+1\)。
然后?
直接连边求最短路即可。
代码
时间复杂度 \(\mathcal{O}(V\log V)\)。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <set>
#define int long long
#define PII pair<int,int>
#define N 100005
using namespace std;
int h,x,y,z;
int dis[N];
bool vis[N];
priority_queue<PII,vector<PII>,greater<PII>> q;
vector<PII> g[N];
signed main(){
cin >> h >> x >> y >> z;
h --;
for (int i = 0;i < x;i ++) dis[i] = 1e18,g[i].push_back({(i + y) % x,y}),g[i].push_back({(i + z) % x,z});
dis[0] = 0;
q.push({0,0});
while(!q.empty()) {
int t = q.top().second;
q.pop();
if (vis[t]) continue;
vis[t] = 1;
for (auto i : g[t])
if (dis[i.first] > dis[t] + i.second) dis[i.first] = dis[t] + i.second,q.push({dis[i.first],i.first});
}
int ans = 0;
for (int i = 0;i < x;i ++)
if (h >= dis[i]) ans += (h - dis[i]) / x + 1;
cout << ans;
return 0;
}
P2371 [国家集训队] 墨墨的等式
分析
上一道题目的扩展版。
代码
时间复杂度 \(\mathcal{O}(V\log V+nV)\)。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <stdlib.h>
#include <algorithm>
#include <vector>
#include <queue>
#define int long long
#define N 500005
#define PII pair<int,int>
using namespace std;
int n,a[N],l,r,dis[N];
vector<PII> g[N];
bool vis[N];
int x;
priority_queue<PII,vector<PII>,greater<PII>> q;
int calc(int t) {
int res = 0;
for (int i = 0;i < x;i ++)
if (t >= dis[i]) res += (t - dis[i]) / x + 1;
return res;
}
signed main(){
cin >> n >> l >> r;
int y;
cin >> x;
n --;
while(n && !x) n --,scanf("%lld",&x);
for (int i = 1;i <= n;i ++) {
scanf("%lld",&y);
for (int i = 0;i < x;i ++) g[i].push_back({(i + y) % x,y});
}
for (int i = 0;i < x;i ++) dis[i] = 1e18;
q.push({0,0});
dis[0] = 0;
while(!q.empty()) {
int t = q.top().second;
q.pop();
if (vis[t]) continue;
vis[t] = 1;
for (auto i : g[t])
if (dis[i.first] > dis[t] + i.second) {
dis[i.first] = dis[t] + i.second;
q.push({dis[i.first],i.first});
}
}
cout << calc(r) - calc(l - 1);
return 0;
}

浙公网安备 33010602011771号