题目描述
题解
设
f(i)
表示只用y和z并且%x=i的所能到达的楼层的最小高度。那么答案为
∑i=0x−1⌊h−f(i)x⌋+1
.
显然
f((i+y)%x)=f(i)+y,f((i+z)%x)=f(i)+z
.这样的话建出图来跑一边最短路就行了。
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
#define LL long long
#define N 100005
LL n;
int x,y,z;
int tot,point[N],nxt[N*2],v[N*2]; LL c[N*2];
LL f[N],ans;
bool vis[N];
queue <int> q;
void addedge(int x,int y,LL z)
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z;
}
void spfa(int u)
{
memset(f,127,sizeof(f)); f[u]=1;
memset(vis,0,sizeof(vis)); vis[u]=true;
while (!q.empty()) q.pop(); q.push(u);
while (!q.empty())
{
int now=q.front(); q.pop();
vis[now]=false;
for (int i=point[now];i;i=nxt[i])
if (f[now]+c[i]<f[v[i]])
{
f[v[i]]=f[now]+c[i];
if (!vis[v[i]])
{
vis[v[i]]=true;
q.push(v[i]);
}
}
}
}
int main()
{
scanf("%lld%d%d%d",&n,&x,&y,&z);
for (int i=0;i<x;++i)
{
addedge(i,(i+y)%x,(LL)y);
addedge(i,(i+z)%x,(LL)z);
}
spfa(1%x);
for (int i=0;i<x;++i)
if (f[i]<=n) ans+=(n-f[i])/(LL)x+1;
printf("%lld\n",ans);
}