hdu 5945 Fxx and game
青年理论计算机科学家Fxx给的学生设计了一款数字游戏。 一开始你将会得到一个数X,每次游戏将给定两个参数x,k,t, 任意时刻你可以对你的数执行下面两个步骤之一: 1.X=X−i(1<=i<=t)。 2.若X为k的倍数,X=X/k。 现在Fxx想要你告诉他最少的运行步骤,使X变成1。
设f[x]为x的最小变为1步数
initialize: f[1]=0
equation: f[x]=min{f[x-i](i<=t),f[x/k](if x%k==0)} (x:1~x)
对于求min{f[x-i](i<=t)} 使用单调队列维护区间最小f[x-i]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstring> #include <cmath> #include <deque> using namespace std; const int N=1e6+10; int f[N],k,t; deque<int>mn; int dfs(int x) { f[1] = 0; mn.clear(); mn.push_back(1); int j = 1; for(int i=2;i<=x;i++) { if(i%k==0) f[i]=min(f[i],f[i/k]+1); while(!mn.empty() and i-mn.front() > t) mn.pop_front(); if(!mn.empty() and i-mn.front() <= t) { f[i]=min(f[i],f[mn.front()]+1); } while(!mn.empty() and f[mn.back()] >= f[i]) mn.pop_back(); mn.push_back(i); } return f[x]; } int main() { int T; cin>>T; while(T--) { memset(f,0x3f,sizeof(f)); int x; cin>>x>>k>>t; if(k>1) cout<<dfs(x)<<endl; else cout<<int(ceil(double(x-1)/t))<<endl; } return 0; }