把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

同余最短路

类似的做法罢了。

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;
}
posted @ 2025-11-03 20:45  high_skyy  阅读(14)  评论(0)    收藏  举报
浏览器标题切换
浏览器标题切换end