同余最短路
以 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;
}