Problem:
Score : 300 points

Problem Statement

You've come to your favorite store Infinitesco to buy some ice tea.

The store sells ice tea in bottles of different volumes at different costs.
Specifically, a 0.25-liter bottle costs Q yen, a 0.5-liter bottle costs H yen, a 1-liter bottle costs S yen, and a 2-liter bottle costs D yen.
The store has an infinite supply of bottles of each type.

You want to buy exactly N liters of ice tea. How many yen do you have to spend?

Constraints

1 \leq Q, H, S, D \leq 10^8

1 \leq N \leq 10^9

All input values are integers.

Input

Input is given from Standard Input in the following format:

Q H S D
N

Output

Print the smallest number of yen you have to spend to buy exactly N liters of ice tea.

Sample Input 1

20 30 70 90
3

Sample Output 1

150

Buy one 2-liter bottle and two 0.5-liter bottles. You'll get 3 liters for 90 + 30 + 30 = 150 yen.

Sample Input 2

10000 1000 100 10
1

Sample Output 2

100

Even though a 2-liter bottle costs just 10 yen, you need only 1 liter.
Thus, you have to buy a 1-liter bottle for 100 yen.

Sample Input 3

10 100 1000 10000
1

Sample Output 3

40

Now it's better to buy four 0.25-liter bottles for 10 + 10 + 10 + 10 = 40 yen.

Sample Input 4

12345678 87654321 12345678 87654321
123456789

Sample Output 4

1524157763907942

Solution in C++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> PII;
 
 
LL MOD = 998244353;
LL power(LL x, LL k) {
	if(x == 0) return 0;
	if(k == 0) return 1;
	LL ret = power(x, k/2);
	ret *= ret;
	ret %= MOD;
	if(k % 2 == 1 ) {
		ret *= x;
		ret %= MOD;
	}
	return ret;
}
 
LL frac(LL x) {
	return power(x, MOD-2);
}
 
vector<LL> kaijo;
vector<LL> inv_kaijo;
 
void init(int N) {
	kaijo.push_back(1);
	for(int i=1; i<=N; i++)
		kaijo.push_back(kaijo.back() * (LL)i % MOD);
	for(int i=0; i<N; i++) {
		inv_kaijo.push_back(frac(kaijo[i]));
	}
	
}
LL comb(LL m, LL n) {
  	LL tmp = kaijo[m];
	tmp = tmp * inv_kaijo[n] % MOD;
	tmp = tmp * inv_kaijo[m-n] % MOD;
	return tmp;
}
 
int main() {
	init(100000);
	string A,B;
	cin >> A >> B;
//	LL N = A.size();
	LL K = 0;
	LL M = 0;
	for(int i=0; i<A.size(); i++) {
		if(A[i] == '1') M++;
		if(A[i] == B[i] && A[i] == '1')
			K++;	
	}
	vector<LL> kanzen(K+10, 0);
	kanzen[0] = 1;
	kanzen[2] = 1;
	kanzen[3] = 2;
	for(int i=4; i<=K; i++) {
		kanzen[i] = (kanzen[i-1] + kanzen[i-2]) * (LL) (i-1);
		kanzen[i] %= MOD;	
	}
	LL mul = 1;
	for(int i=0; i<=K; i++) {
		kanzen[i] *= mul;
		mul *= (LL)(i+1);
		mul %= MOD;
	}
	vector<LL> dp(K+1, 0);
	dp[K] = 1;
	LL ans = 0;
if(M==K) ans += kanzen[K];
	for(int z=0; z<M; z++) {
	//	vector<LL> tmp(K+1, 0);
		LL N = M-z;
		for(LL k=0; k<=K; k++) {
			//if(k>=2) tmp[k-2] += dp[k] * k * (k-1);
			if(k>=1) dp[k-1] += dp[k] * (N-k+1) * k;
			dp[k] = dp[k] * (N-k) * (N-k);
		}
		for(int i=0; i<=K; i++) {
		//	cout << i  << " "<< dp[i] << endl;
			
			dp[i] = dp[i] % MOD;
			if(N == i+1) {
				ans += dp[i] * kanzen[i] % MOD * comb(M, i) % MOD;
	//			cout << dp[i] << " " << kanzen[i] << endl;
			}
		}
		
	}
	ans %= MOD;
	cout << ans << endl;
	//cout << dp[0] << endl;	
	
	
	return 0;	
}