輸入描述
輸出描述
輸入樣例
輸出樣例
題意:中文題,不再贅述;
思路: BC題解如下:
從後往前推,可以得到狀態轉移方程dp[i]=(dp[k*i],dp[i+l])+1{1<=l<=t}
根據這個轉移方程我們需要快速求得min{dp[i+l]}(1<=l<=t)
我們知道這種形式的就是單調隊列優化dp的標准形式
維護一個dp[i]從隊頭到隊尾遞增的隊列 每次算好dp[i]的時候把隊尾中dp值大於等於dp[i]的都出隊 (出隊都是下標比i大的,值又沒i優,是無用的)
然後dp[i]=min(dp[a[pre]],dp[k*i])+1
代碼如下:
#include <iostream> #include <algorithm> #include <stdio.h> #include <cstring> #include <cmath> #include <queue> #include <set> #include <bitset> using namespace std; typedef long long LL; int dp[1000005],a[1000005]; int pre,tail; int main() { int T,x,k,t; cin>>T; while(T--) { scanf("%d%d%d",&x,&k,&t); pre=0,tail=0; a[tail++]=x; dp[x]=0; for(int i=x-1;i>=1;i--) { dp[i] = (t!=0)?dp[a[pre]]+1:9999999; if((1LL*i*k)<=(LL)x) dp[i]=min(dp[i],dp[i*k]+1); if(a[pre]-t==i) pre++; while(dp[a[tail-1]]>=dp[i]&&tail>pre) tail--; a[tail++]=i; } printf("%d\n",dp[1]); } return 0; }