設$f[i]$為最優策略下除錯$i$行程式碼的時間,則:
$f[1]=0$
$f[i]=\min((j-1)\times p+f[\lceil\frac{i}{j}\rceil])+r$
意義為列舉printf語句的個數,然後儘量均分,並假設壞點在最大的段落裡。
考慮記憶化搜尋,注意到對於每個$i$來說只有$O(\sqrt{i})$個決策有用,所以時間複雜度為$O(n^\frac{3}{4})$。
#include<cstdio> typedef long long ll; int n,r,p,i;ll f[1000010]; inline void up(ll&a,ll b){if(a>b)a=b;} ll F(int n){ if(n<2)return 0; if(f[n])return f[n]; ll t=1LL*n*p; for(int i=2;i<n;i=(n-1)/((n-1)/i)+1)up(t,1LL*i*p+F((n-1)/i+1)); return f[n]=t+r-p; } int main(){ scanf("%d%d%d",&n,&r,&p); return printf("%lld",F(n)),0; }