【hdu 5945】Fxx and game(递推|dp+单调队列)
Fxx and game
Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 347 Accepted Submission(s): 78
Problem Description
Young theoretical computer scientist Fxx designed a game for his students.
In each game, you will get three integers X,k,t.In each step, you can only do one of the following moves:
1.X=X−i(0<=i<=t).
2.if k|X,X=X/k.
Now Fxx wants you to tell him the minimum steps to make X become 1.
In each game, you will get three integers X,k,t.In each step, you can only do one of the following moves:
1.X=X−i(0<=i<=t).
2.if k|X,X=X/k.
Now Fxx wants you to tell him the minimum steps to make X become 1.
Input
In the first line, there is an integer T(1≤T≤20) indicating
the number of test cases.
As for the following T lines, each line contains three integers X,k,t(0≤t≤106,1≤X,k≤106)
For each text case,we assure that it's possible to make X become 1。
As for the following T lines, each line contains three integers X,k,t(0≤t≤106,1≤X,k≤106)
For each text case,we assure that it's possible to make X become 1。
Output
For each test case, output the answer.
Sample Input
2
9 2 1
11 3 3
Sample Output
4
3
Source
Recommend
【题解】【递推|dp+单调队列】
【从小往大处理:从1枚举到n,f[i]表示i最少经几次变换能变到1】
【f[i]=max(f[j](max(i-t,1)<=j<i),[k|i]f[i/k])+1,每次先判断当前数是否能整除k,再与f[j](max(i-t,1)<=j<i)中的每一个相比较,取最大值】
【那么,我们可以发现,实际就是在f[i/k](i能整除k)和f[j](max(i-t,1)<=j<i)的最大值中选一个大的。那么,我们可以用单调队列来维护f[j](max(i-t,1)<=j<i)的最大值,这样就能省掉一重循环,就可以AC!】
[考试时,用dfs实现上述过程,结果栈溢出!]
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int t,k,n,T;
int f[1000010],que[1000010],minn[1000010];
int main()
{
// freopen("int.txt","r",stdin);
// freopen("my.txt","w",stdout);
int i,j;
scanf("%d",&T);
while(T--)
{
memset(f,127,sizeof(f));
int head,tail; head=tail=1;
f[1]=0; minn[tail]=0; que[tail]=1;
scanf("%d%d%d",&n,&k,&t);
for(i=2;i<=n;++i)
{
if(!(i%k)) f[i]=f[i/k]+1;
int m=max(i-t,1);
while(tail>head&&que[head]<m) head++;
f[i]=min(f[i],minn[head]+1);
while(tail>=head&&f[i]<=minn[tail]) tail--;
tail++; minn[tail]=f[i]; que[tail]=i;
}
printf("%d\n",f[n]);
}
return 0;
}
既然无能更改,又何必枉自寻烦忧