洛谷P3403跳楼机
思路:
由题,我们可到达的楼层为
a
x
+
b
y
+
c
z
(
a
,
b
,
c
≥
0
)
ax+by+cz(a,b,c\ge0)
ax+by+cz(a,b,c≥0)。
我们假设一个数
k
k
k是只通过操作2,3得到的,即
k
=
b
y
+
c
z
k=by+cz
k=by+cz。式子就变成了求满足
a
x
+
k
≤
h
ax+k\le h
ax+k≤h中
x
x
x的数量。易得,通过操作1,能够到达的楼层数量为
⌊
h
−
k
x
⌋
+
1
\lfloor\cfrac{h-k}{x}\rfloor+1
⌊xh−k⌋+1。
考虑去掉重复的部分。因为如果存在
k
1
≡
k
2
(
m
o
d
x
)
,
k
1
≤
k
2
k_1\equiv k_2(\mod x),k_1\le k_2
k1≡k2(modx),k1≤k2。那么一定存在
a
a
a使
k
1
+
a
x
=
k
2
k_1+ax=k_2
k1+ax=k2成立。所以对于余数相同的情况,我们只需要最小的一个
k
k
k即可。
可得
d
i
=
min
{
k
∣
k
m
o
d
x
=
i
,
k
=
b
y
+
c
z
}
d_i=\min\{k|k\mod x=i,k=by+cz\}
di=min{k∣kmodx=i,k=by+cz}。
在一层楼可以上升
y
,
z
y,z
y,z层楼,贡献分别为
y
,
z
y,z
y,z。相当于建边:
i
⟶
y
(
i
+
y
)
m
o
d
x
i\overset{y}{\longrightarrow} {(i+y)\mod{x}}
i⟶y(i+y)modx
i
⟶
z
(
i
+
z
)
m
o
d
x
i\overset{z}{\longrightarrow} {(i+z)\mod{x} }
i⟶z(i+z)modx
求完最短路
d
i
d_i
di之后,答案就是:
∑
i
=
0
,
d
i
≤
h
x
−
1
(
⌊
h
−
d
i
x
⌋
+
1
)
\sum\limits_{i=0,d_i\le h}^{x-1}(\lfloor\cfrac{h-d_i}{x}\rfloor+1)
i=0,di≤h∑x−1(⌊xh−di⌋+1)
注意的一点是,INF的设置要大于long long。因为
h
h
h的最大值为
2
63
−
1
2^{63}-1
263−1。
代码:
#include<bits/stdc++.h>
#define pii pair<int,int>
#define int unsigned long long
#define cl(x,y) memset(x,y,sizeof(x))
#define loop(x,y,z) for(x=y;x<=z;x++)
#define reve(x,y,z) for(x=y;x>=z;x--)
#define ct cerr<<"Time elapsed:"<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n";
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define all(x) x.begin(),x.end()
#define lson x<<1,l,mid
#define rson x<<1|1,mid+1,r
const int N=1e6+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
const double pi=acos(-1);
using namespace std;
vector<pii> e[N];
int d[N],vis[N];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int h,x,y,z,INF=1,i;
cin>>h>>x>>y>>z;
for(i=1;i<=63;i++)
INF*=2;
for(i=0;i<x;i++)
{
e[i].pb(mp((i+y)%x,y));
e[i].pb(mp((i+z)%x,z));
d[i]=INF;
}
priority_queue<pii,vector<pii>,greater<pii> > q;
d[1%x]=1;
q.push(mp(0,1%x));
while(!q.empty())
{
int u=q.top().se;
q.pop();
if(vis[u])
continue;
vis[u]=1;
for(i=0;i<e[u].size();i++)
{
int v=e[u][i].fi,w=e[u][i].se;
if(d[v]>d[u]+w)
{
d[v]=d[u]+w;
q.push(mp(d[v],v));
}
}
}
int ans=0;
for(i=0;i<x;i++)
if(d[i]<=h)
ans+=(h-d[i])/x+1;
cout<<ans<<endl;
return 0;
}