同余最短路

以 P3403 跳楼机为例:
\(h\gets h-1\),相当于求 \(ax+by+cz=k(k\le h)\)\(k\) 的个数。
\(d_u\) 表示到达满足 \(k\bmod x=u\) 最小的 \(k\).
\(d_u+y\to d_{(u+y)\bmod x},d_u+z\to d_{(u+z)\bmod x}\)
发现这是一个最短路的形式,直接可以求出,
求出所有 \(d_i\),若 \(h>d_i\),那么对答案的贡献是 \((h-d_i)/x+1\).

code
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int N=1e5+10;
long long h,x,y,z,d[N];
bool vis[N];
queue<int> q;
int main() {
	scanf("%lld%lld%lld%lld",&h,&x,&y,&z); h--;
	memset(d,63,sizeof d); d[0]=0;
	q.push(0);
	for(; q.size(); ) {
		int u=q.front(),v; q.pop();
		vis[u]=0;
		v=(u+y)%x;
		if(d[v]>d[u]+y) {
			d[v]=d[u]+y;
			if(!vis[v]) q.push(v),vis[v]=1;
		}
		v=(u+z)%x;
		if(d[v]>d[u]+z) {
			d[v]=d[u]+z;
			if(!vis[v]) q.push(v),vis[v]=1;
		}
	}
	long long Ans=0;
	for(int i=0; i<x; i++) {
		if(h>=d[i]) Ans+=(h-d[i])/x+1;
	}
	printf("%lld\n",Ans);
	return 0;
}
posted @ 2023-09-24 19:56  s1monG  阅读(2)  评论(1编辑  收藏  举报