luoguP3403 跳楼机
是这题的弱化版本。
考虑 \(\bmod x\) 意义下的同余等价类。
每个 \(i\in [0,x-1]\) 向 \((i+y)\bmod x\) 和 \((i+z)\bmod x\) 连边。
要注意的是起点为 \(1\bmod x\),起始 \(dis\) 为 \(1\)。
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
const int V=1e5+5;
ll h;
int x,y,z,mn;
struct node{
int v;ll dis;
bool operator<(const node& t)const{return dis>t.dis;}
};
vector<node> g[V];
ll dis[V];
void dij(int st){
memset(dis,0x3f,sizeof dis);
priority_queue<node> q;
q.push({st,dis[st]=1});
while(!q.empty()){
auto t=q.top();q.pop();
int u=t.v;
if(dis[u]!=t.dis) continue;
for(auto i:g[u]){
int v=i.v,w=i.dis;
if(dis[v]>dis[u]+w)
dis[v]=dis[u]+w,q.push({v,dis[v]});
}
}
}
ll query(ll x){
ll sum=0;
for(int i=0;i<mn;++i)
if(dis[i]<=x) sum+=(x-dis[i])/mn+1;
return sum;
}
int main(){
scanf("%lld %d %d %d",&h,&x,&y,&z);
if(x>y) swap(x,y);if(x>z) swap(x,z);
mn=x;
for(int i=0;i<mn;++i) g[i].push_back({(i+y)%mn,y}),g[i].push_back({(i+z)%mn,z});
dij(1%mn);
printf("%lld",query(h));
}

浙公网安备 33010602011771号