Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 360 Accepted Submission(s): 84
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.
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。
Output
For each test case, output the answer.
Sample Input
2
9 2 1
11 3 3
Sample Output
4
3
Source
BestCoder Round #89
【题解】
f[i] = min(f[i],f[i/k]+1);
f[i] = min(f[i],f[i-t..i-1]+1);
第二行那个转移可用一个单调队列优化;
因为f[i+1]>=f[i];
dl的最左边维护的是i-t..i-1这个区间内f值最小的点的下标;然后往右f值依次递增;
如果新加入的点i,f[i]小于这个dl最右边x对应值f[x],则把x挤掉(那些被挤掉的元素是肯定没有用了的,如果到了某个时刻f[i]被挤掉了,因为i>x,则x肯定也要被挤掉),重复上述步骤;
就能维护一个单调队列;
有点厉害.
#include <cstdio>
#include <cmath>
#include <set>
#include <map>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
#include <string>
#define lson L,m,rt<<1
#define rson m+1,R,rt<<1|1
#define LL long long
using namespace std;
const int MAXN = 2e6;
const int dx[5] = {0,1,-1,0,0};
const int dy[5] = {0,0,0,-1,1};
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
int x,k,t,l,r;
int f[MAXN],dl[MAXN];
void input_LL(LL &r)
{
r = 0;
char t = getchar();
while (!isdigit(t)) t = getchar();
LL sign = 1;
if (t == '-')sign = -1;
while (!isdigit(t)) t = getchar();
while (isdigit(t)) r = r * 10 + t - '0', t = getchar();
r = r*sign;
}
void input_int(int &r)
{
r = 0;
char t = getchar();
while (!isdigit(t)) t = getchar();
int sign = 1;
if (t == '-')sign = -1;
while (!isdigit(t)) t = getchar();
while (isdigit(t)) r = r * 10 + t - '0', t = getchar();
r = r*sign;
}
int main()
{
//freopen("F:\\rush.txt", "r", stdin);
int T;
input_int(T);
while (T--)
{
memset(f,INF,sizeof(f));
input_int(x);input_int(k);input_int(t);
l = 1;r = 1;dl[r] = 1;
f[1] = 0;
for (int i = 2;i <= x;i++)
{
while (l<=r && dl[l]<i-t)l++;
if ((i%k)==0)
f[i] = min(f[i],f[i/k]+1);
if (l <=r)
f[i] = min(f[i],f[dl[l]]+1);
while (l<=r && f[i]<f[dl[r]]) r--;
dl[++r] = i;
}
printf("%d\n",f[x]);
}
return 0;
}