可提交的傳送門http://acm.hdu.edu.cn/showproblem.php?pid=5945
分析:這道題目可以采用動態規劃來解決
設f[i]表示把i變成1的最小代價。
所以有:f[i] = min{f[(1-t) ~ (i-1)]}+1
特別的,對於i % k == 0 f[i] = min{f[i],f[i/k] + 1}
我們可以先忽略掉特判的一步,這樣,f[i]就來自於f[(1-t) ~ (i-1)]之間的最小值了
我們發現這個問題轉換成了RMQ問題,可以在logn內解決
可以用單調隊列優化dp,這樣可以做到復雜度O(n)
1 #include <queue>
2 #include <cstdio>
3 #include <cstring>
4 #include <iostream>
5 #include <algorithm>
6 using namespace std;
7 typedef long long ll;
8 inline void read(int &x){
9 x=0;char ch;bool flag = false;
10 while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
11 while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
12 }
13 inline int cat_max(const int &a,const int &b){return a>b ? a:b;}
14 inline int cat_min(const int &a,const int &b){return a<b ? a:b;}
15 const int maxn = 1000010;
16 const int inf = 0x3f3f3f3f;
17 int f[maxn],q[maxn],l,r,ans;
18 inline void work(){
19 int n,k,t;
20 read(n);read(k);read(t);
21 if(t == 0){
22 for(ans=0;n>1;++ans) n /= k;
23 printf("%d\n",ans);
24 return;
25 }
26 l = r = 0;f[1] = 0;
27 q[0] = 1;
28 for(int i=2;i<=t+1 && i <= n;++i) f[i] = 1,q[++r] = i;
29 for(int i=t+2;i<=n;++i){
30 if(i % k == 0 && k != 1) f[i] = f[i/k] + 1;
31 else f[i] = inf;
32 while(l <= r && q[l] < (i - t)) ++l;
33 f[i] = cat_min(f[i],f[q[l]] + 1);
34 while(l <= r && f[q[r]] >= f[i]) --r;
35 q[++r] = i;
36 }
37 printf("%d\n",f[n]);
38 }
39 int main(){
40 int T;read(T);
41 while(T--) work();
42 getchar();getchar();
43 return 0;
44 }