题目背景
DJL 为了避免成为一只咸鱼,来找 srwudi 学习压代码的技巧。
题目描述
Srwudi 的家是一幢 ℎh 层的摩天大楼。由于前来学习的蒟蒻越来越多,srwudi 改造了一个跳楼机,使得访客可以更方便的上楼。
经过改造,srwudi 的跳楼机可以采用以下四种方式移动:
- 向上移动 �x 层;
- 向上移动 �y 层;
- 向上移动 �z 层;
- 回到第一层。
一个月黑风高的大中午,DJL 来到了 srwudi 的家,现在他在 srwudi 家的第一层,碰巧跳楼机也在第一层。DJL 想知道,他可以乘坐跳楼机前往的楼层数。
输入格式
第一行一个整数 ℎh,表示摩天大楼的层数。
第二行三个正整数,分别表示题目中的 �,�,�x,y,z。
输出格式
一行一个整数,表示 DJL 可以到达的楼层数。
输入输出样例
输入 #1复制
15 4 7 9
输出 #1复制
9
输入 #2复制
33333333333 99005 99002 100000
输出 #2复制
33302114671
这是一道伪装成数论的图论!!!
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#define int long long
#define wk(x) write(x),putchar(' ')
#define wh(x) write(x),putchar('\n')
#define r(x) read(x)
#define INF 0x3f3f3f3f
const int N=100005;
using namespace std;
void read(int&);
void write(int);
void dfs(int,int);
void qsort(int,int);
int xx,yy,zz,n,m,k,t,jk,tot,cnt,ans,sum,num,answer;
int a[N],dis[N],vis[N],p[N];
int head[2*N],to[2*N],nxt[2*N],val[2*N];
void add(int x,int y,int z)
{
to[++cnt]=y;
nxt[cnt]=head[x];
val[cnt]=z;
head[x]=cnt;
}
void spfa()
{
dis[1]=1;vis[1]=1;p[++p[0]]=1;
while(p[0]>0)
{
int u=p[p[0]];
p[0]--;vis[u]=0;
for(int i=head[u];i;i=nxt[i])
{
int v=to[i],w=val[i];
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
if(vis[v]==0) p[++p[0]]=v,vis[v]=1;
}
}
}
}
signed main()
{
memset(dis,INF,sizeof(dis));
r(n);
r(xx),r(yy),r(zz);
if(xx==1||yy==1||zz==1) printf("%lld",n);
else
{
for(int i=0;i<xx;i++)
{
add(i,(i+zz)%xx,zz);
add(i,(i+yy)%xx,yy);
}
spfa();
for(int i=0;i<xx;i++)
{
if(n>=dis[i]) ans+=(n-dis[i])/xx+1;
}
printf("%lld\n",ans);
}
return 0;
}
void read(int &x)
{
x=0;int ff=1;
char ch=getchar();
while (ch<'0'||ch>'9')
{
if(ch=='-') ff=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
x*=ff;return;
}
void write(int x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
return;
}