题意: 有4种操作,你需要用最少的操作使得0变成n.
- .
反过来考虑这个问题,
有个显然的性质:
最优情况下,对于n,经过若干次
后再除以
,得到的值
,一定满足
.
因为如果
,那么先除再
肯定更快.
对于
,同理.
再来一个性质: .
然后状态复杂度大概: .
暴力出奇迹!
#include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define gc getchar()
using namespace std;
typedef long long ll;
template<class o> void qr(o&x) {
char c=gc; x=0; int f=1;
while(!isdigit(c)){if(c=='-')f=-1; c=gc;}
while(isdigit(c))x=x*10+c-'0',c=gc;
x*=f;
}
int T;
ll n,a,b,c,d;
map<ll,ll> s;
ll f(ll n) {
if(s.count(n)) return s[n];
ll res=n<1e18/d?n*d:(ll)1e18;
ll l1=(n/2)*2,r1=((n+1)/2)*2;
ll l2=(n/3)*3,r2=((n+2)/3)*3;
ll l3=(n/5)*5,r3=((n+4)/5)*5;
res=min(res,(n-l1)*d+f(l1/2)+a);
res=min(res,(r1-n)*d+f(r1/2)+a);
res=min(res,(n-l2)*d+f(l2/3)+b);
res=min(res,(r2-n)*d+f(r2/3)+b);
res=min(res,(n-l3)*d+f(l3/5)+c);
res=min(res,(r3-n)*d+f(r3/5)+c);
return s[n]=res;
}
int main() {
qr(T); while(T--) {
qr(n); qr(a); qr(b); qr(c); qr(d);
s.clear(); s[0]=0; s[1]=d; printf("%lld\n",f(n));
}
return 0;
}