题目大意
有一幢h层的大楼,有一个跳楼机可以移动,初始时在一楼。
跳楼机可以采用以下四种方式移动:
- 向上移动x层
- 向上移动y层
- 向上移动z层
- 回到第一层
给定
Data Constraint
h≤1018 , x,y,z≤105
题解
我们考虑只记向上移动y层和移动z层的方案,然后可以再移动x层多少次是可以计算的。设当前到达了c层,那么这种情况贡献的方案数就是
设di表示最小的c满足
- di+y→d(i+y)mod x
- di+z→d(i+z)mod x
观察到转移的实质其实与最短路类似。所以SPFA跑一下就好了。最后Ans=∑⌊h−dix⌋+1
SRC
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std ;
#define N 1000000 + 10
typedef long long ll ;
bool vis[N] ;
int d[10*N] ;
ll Dist[N] ;
int x , y , z ;
ll h , ans ;
void SPFA() {
memset( Dist , 63 , sizeof(Dist) ) ;
int i = 0 , j = 1 ;
d[1] = 1 % x ;
Dist[1%x] = 1 ;
while ( i < j ) {
i ++ ;
int now = d[i] ;
int s = (now + y) % x ;
if ( Dist[now] + y < Dist[s] ) {
Dist[s] = Dist[now] + y ;
if ( !vis[s] ) {
vis[s] = 1 ;
d[++j] = s ;
}
}
s = (now + z) % x ;
if ( Dist[now] + z < Dist[s] ) {
Dist[s] = Dist[now] + z ;
if ( !vis[s] ) {
vis[s] = 1 ;
d[++j] = s ;
}
}
vis[now] = 0 ;
}
}
int main() {
scanf( "%lld%d%d%d" , &h , &x , &y , &z ) ;
SPFA() ;
for (int i = 0 ; i < x ; i ++ ) {
if ( Dist[i] > h ) continue ;
ans += (h - Dist[i]) / x + 1 ;
}
printf( "%lld\n" , ans ) ;
return 0 ;
}
以上.