傳送門c++
思路:將問題倒着考慮,從 n n n到0. 顯然每一步有4種方式。ide
可是對於 k = 2 , 3 , 5 k=2,3,5 k=2,3,5要知足 2 ∣ n , 3 ∣ n , 5 ∣ n 2|n,3|n,5|n 2∣n,3∣n,5∣n才行。因此這三種方式分別產生兩種狀況,spa
向上取整到達和向下取整到達。code
即 [ n / 2 , ( n + 1 ) / 2 ] , [ n / 3 , ( n + 1 ) / 3 ] , [ n / 5 , ( n + 4 ) / 5 ] [n/2,(n+1)/2],[n/3,(n+1)/3],[n/5,(n+4)/5] [n/2,(n+1)/2],[n/3,(n+1)/3],[n/5,(n+4)/5].get
所以能夠進行 d f s dfs dfs,由於數據較大,因此應該採用 記憶化搜索,用 m a p map map記錄一下當前 n n n的最小值。it
時間複雜度: c n t ( n 2 a × 3 b × 5 c ) cnt(\dfrac{n}{2^a\times 3^b\times 5^c}) cnt(2a×3b×5cn)(狀態數)class
AC代碼:test
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+5; #define mst(a) memset(a,0,sizeof a) ll a,b,c,d,n; unordered_map<ll,ll>mp; ll dfs(ll n){ if(!n) return 0; if(n==1) return d; if(mp[n]) return mp[n]; ll res=1e18; if(n<res/d) res=n*d; res=min(res,a+n%2*d+dfs(n/2)); res=min(res,a+(2-n%2)*d+dfs((n+1)/2)); res=min(res,b+n%3*d+dfs(n/3)); res=min(res,b+(3-n%3)*d+dfs((n+2)/3)); res=min(res,c+n%5*d+dfs(n/5)); res=min(res,c+(5-n%5)*d+dfs((n+4)/5)); mp[n]=res; return res; } int main(){ int t; scanf("%d",&t); while(t--){ mp.clear(); scanf("%lld%lld%lld%lld%lld",&n,&a,&b,&c,&d); printf("%lld\n",dfs(n)); } return 0; }