1. 程式人生 > WINDOWS開發 >AtCoder Grand Contest 044 A Pay to Win 貪心

AtCoder Grand Contest 044 A Pay to Win 貪心

LINK:Pay to Win

自閉了 比賽的時候推出來正解了 以為複雜度不對 寫完扔了 沒拿map存狀態就扔了23333...

一個T點:在更新map的時候 >不要寫成>= 不然會徒勞的增加複雜度 被這個東西坑了好幾次了。

思路:如果直接從1到n這樣增加 很茫然 不知道要乘什麼。

容易想到倒著做 從n到1這樣。這樣每次就知道到底可以除誰。

容易想到 x-w/d比x/d-w 優。

所以每次先考慮除以什麼 如果要除以2 那麼顯然應該是2的倍數 3,5同理。

然後用map存狀態 可以發現總狀態量是1e5的 所以可以通過。

const ll MAXN=100010;
ll T;
ll n,A,B,C,D,ans;
map<ll,ll>H;
priority_queue<pii>q;
inline void gx(ll x,ll w)
{
	if(w>=ans)return;
	if(H.find(x)==H.end())H[x]=w,q.push(mk(x,-w));
	else
	{
		if(w>=H[x])return;
		H[x]=w;q.push(mk(x,-w));
	}
}
signed main()
{
	//freopen("1.in","r",stdin);
	get(T);
	while(T--)
	{
		get(n);get(A);get(B);get(C);get(D);
		H.clear();q.push(mk(n,0));
		ans=INF;H[n]=0;
		int cnt=0;
		while(q.size())
		{
			ll x=q.top().F;
			ll w=-q.top().S;
			q.pop();
			if(w>ans)continue;
			if(H[x]!=w)continue;
			//考慮直接減到0
			if(INF/D>x)ans=min(ans,D*x+w);
			if(x%2)gx(x/2,w+D+A),gx(x/2+1,w+D+A);
			else gx(x/2,w+A);
			if(x%3)gx(x/3,w+x%3*D+B),gx(x/3+1,w+(3-x%3)*D+B);
			else gx(x/3,w+B);
			if(x%5)gx(x/5,w+x%5*D+C),gx(x/5+1,w+(5-x%5)*D+C);
			else gx(x/5,w+C);
			//put(++cnt);
		}
		putl(ans);
	}
	return 0;
}