A - Pay to Win(记忆化搜索)

A - Pay to Win(记忆化搜索)

传送门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 2n,3n,5n才行。因此这三种方式分别产生两种状况,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;
}
相关文章
相关标签/搜索