HDU 5945 / BestCoder Round #89 1002 Fxx and game 单调队列优化DP
Fxx and game
问题描述
青年理论计算机科学家Fxx给的学生设计了一款数字游戏。
一开始你将会得到一个数\:XX,每次游戏将给定两个参数\:k,tk,t, 任意时刻你可以对你的数执行下面两个步骤之一:
1.\:X = X - i(1 <= i <= t)1.X=X−i(1<=i<=t)。
2.\:2.若\:X\:X为\:k\:k的倍数,X = X / kX=X/k。
现在Fxx想要你告诉他最少的运行步骤,使\:X\:X变成\:11。
输入描述
第一行一个整数\:T(1\leq T\leq20)\:T(1≤T≤20)表示数据组数。
接下来\:T\:T行,每行三个数\:X,k,t(0\leq t\leq10^6,1\leq X,k\leq10^6)X,k,t(0≤t≤106,1≤X,k≤106)
数据保证有解。
输出描述
输出共\:T\:T行。
每行一个整数表示答案。
输入样例
2 9 2 1 11 3 3
输出样例
4 3
题解:
看到题解眼泪掉下来
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define ls i<<1 #define rs ls | 1 #define mid ((ll+rr)>>1) #define pii pair<int,int> #define MP make_pair typedef long long LL; const long long INF = 1e18+1LL; const double Pi = acos(-1.0); const int N = 2e6+10, M = 2e5+20, mod = 1e9+7, inf = 2e9; int X,k,t,dp[N],p[N]; int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d%d",&X,&k,&t); for(int i = 2; i <= X; ++i) dp[i] = 0; dp[1] = 0; int l = 0,r = 0; p[1] = 1;l = r = 1; for(int i = 2; i <= X; ++i) { while(p[l] + t < i && l <= r) l++; dp[i] = inf; if(i % k == 0) dp[i] = dp[i/k] + 1; if (l<=r) dp[i] = min(dp[p[l]]+1,dp[i]); while(r - l >= 0 && dp[i] <= dp[p[r]]) r--; p[++r] = i; } printf("%d\n",dp[X]); } return 0; }