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=Xi(1<=i<=t)。

2.\:2.\:X\:X\:k\:k的倍数,X = X / kX=X/k。

现在Fxx想要你告诉他最少的运行步骤,使\:X\:X变成\:11。
输入描述
 
第一行一个整数\:T(1\leq T\leq20)\:T(1T20)表示数据组数。

接下来\:T\:T行,每行三个数\:X,k,t(0\leq t\leq10^6,1\leq X,k\leq10^6)X,k,t(0t106​​,1X,k106​​)

数据保证有解。
输出描述
输出共\: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;
}

 

posted @ 2016-10-29 21:53  meekyan  阅读(380)  评论(0编辑  收藏  举报