ZROI#1012
考虑如果没有 (backspace) 操作,那就是个 (SB) 递推.
考虑加入 (backspce) 后有什么影响,那就是出现环状转移.
那咋办,显然所有的转移一定都是正权,也就是不会有一种转移,使状态变化的同时减少答案次数.
我们知道,平时 (DP) 的转移就是一张边带权的 (DAG) , 我们要求的答案其实就是这张 (DAG) 上从起始点到目标点的最短/长路.
那么这个题,我们不如就把这样一张转移图建出来,直接采用 (SPFA) 的方式以重复入队来完成转移,因为一定会有一些状态是不在环中的,所以环上的状态可以通过多次入队调整松弛完成最优化.
建边的时候要考虑全面,漏掉一种边很可能就会收获 (0pts) 的好成绩.
(backspace) 操作肯定不会有很多,所以边数并不巨大,理论上需要 (n imes log_2{n}) 条,而实际只需要向后 ( imes 5) 就能 (AC).(多了会 (TLE))
当然,可能某些人的代码需要卡卡常.
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC target("sse,sse2,sse3,sse4.1,sse4.2,popcnt,abm,mmx,avx")
#pragma comment(linker,"/STACK:102400000,102400000")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <queue>
#include <cmath>
#include <ctime>
#include <map>
#include <set>
#define MEM(x,y) memset ( x , y , sizeof ( x ) )
#define rep(i,a,b) for (int i = (a) ; i <= (b) ; ++ i)
#define per(i,a,b) for (int i = (a) ; i >= (b) ; -- i)
#define pii pair < int , int >
#define one first
#define two second
#define rint read<int>
#define pb push_back
#define db double
#define ull unsigned long long
#define lowbit(x) ( x & ( - x ) )
using std::queue ;
using std::set ;
using std::pair ;
using std::max ;
using std::min ;
using std::priority_queue ;
using std::vector ;
using std::swap ;
using std::sort ;
using std::unique ;
using std::greater ;
template < class T >
inline T read () {
T x = 0 , f = 1 ; char ch = getchar () ;
while ( ch < '0' || ch > '9' ) {
if ( ch == '-' ) f = - 1 ;
ch = getchar () ;
}
while ( ch >= '0' && ch <= '9' ) {
x = ( x << 3 ) + ( x << 1 ) + ( ch - 48 ) ;
ch = getchar () ;
}
return f * x ;
}
const int N = 1e7 + 100 ;
const int inf = 0x7f7f7f7f ;
struct edge { int to , next , data ; } e[N<<1] ;
queue < int > q ;
int n , x , dis[N] , head[N] , tot , maxn = - inf ;
bool vis[N] ;
inline void build (int u , int v , int w) {
e[++tot].next = head[u] ; e[tot].to = v ;
e[tot].data = w ; head[u] = tot ; return;
}
inline void SPFA (int cur) {
MEM ( dis , 0x7f ) ; MEM ( vis , 0 ) ;
q.push ( cur ) ; vis[cur] = true ; dis[cur] = 0 ;
while ( ! q.empty () ) {
int j = q.front () ; q.pop () ; vis[j] = false ;
for (int i = head[j] ; i ; i = e[i].next) {
int k = e[i].to ;
if ( dis[k] > dis[j] + e[i].data ) {
dis[k] = dis[j] + e[i].data ;
if ( ! vis[k] ) q.push ( k ) , vis[k] = true ;
}
}
}
return ;
}
signed main (int argc , char * argv[]) {
x = rint () ; n = rint () ; maxn = max ( n , x ) + 1 ;
rep ( i , 0 , maxn ) {
build ( i , i + 1 , 1 ) ;
build ( i , i - 1 , 1 ) ;
build ( i , 0 , 3 ) ;
}
rep ( i , 1 , maxn )
for (int j = 1 ; j <= 5 && i * j <= maxn ; ++ j)
build ( i , i * j , 4 + 2 * ( j - 1 ) ) ;
SPFA ( x ) ; printf ("%lld
" , dis[n] ) ;
return 0 ;
}