#include #include #include #include #include #define REP(i,a,b) for(i=a;ik);if(i>=j)break;t=d[i];d[i]=d[j];d[j]=t;}intSort(d,i);intSort(d+j+1,s-j-1);} int N, B; ll M, L; int node, ed, state[30000][50], state_sum[30000], edge[30000][2]; ull state_hs[30000]; /* get hash of state s */ ull get_hash(int s[]){ int i; ull hs = 0; rep(i,N) hs = hs*1007 + s[i]; return hs; } /* add the new node denoting the state s */ int add_node(int s[]){ int i; rep(i,N) state[node][i] = s[i]; state_sum[node] = 0; rep(i,N) state_sum[node] += s[i]; state_hs[node] = get_hash(s); ullHashSet(state_hs[node], node+1); return node++; } /* get the node number of the state s */ /* if not exist, create a new node and return the new node number */ int get_node(int s[]){ int k; ull hs = get_hash(s); k = ullHashGet(hs) - 1; if(k>=0) return k; return add_node(s); } ll dp[30000]; ll solve(int n){ int i,j; ll res, tmp1, tmp2, k; if(dp[n] >= 0) return dp[n]; if(edge[n][1]==-1){ /* only one color of balls are remained */ tmp1 = solve(edge[n][0]); res = (tmp1 + B) / (B+1); /* Tomya may bet all her coins, therefore, if Tomya has res coins, then Tomya can get tmp1 coins in the next state (If res <= L)*/ if(res > L) res = tmp1 - L*B; /* res is too large, so Tomya bets L coins */ } else { tmp1 = solve(edge[n][0]); /* the largest color is chosen by Ciel */ tmp2 = solve(edge[n][1]); /* the second largest color is chosen by Ciel */ assert(tmp1 >= tmp2); res = (tmp1 + B*tmp2 + B) / (B+1); /* If Tomya has res coins, then Tomya can reach tmp1 and tmp2 in corresponding states. (If below k <= L) */ k = res - tmp2; /* Tomya may bet k coins */ if(k > L){ /* k is too large, so Tomya bets L coins */ res = tmp2 + L; if(res > tmp1 - B*L) res = tmp1 - B*L; } } return dp[n] = res; } int main(){ int i, j, k, m; int T; int S[50]; ll a, b, c, d; assert( scanf("%d",&T)==1 ); assert( 1<=T && T<=5 ); while(T--){ assert( scanf("%d%d%lld%lld",&N,&B,&M,&L)==4 ); assert( 1<=N && N<=30 ); assert( 1<=B && B<=30 ); assert( 1LL<=M && M<=1000000000000LL ); assert( 1LL<=L && L<=1000000000000LL ); rep(i,N) assert( scanf("%d",S+i)==1 ), assert( 1<=S[i] && S[i]<=30 ); /* begin - generate graph */ node = 0; ullHashClear(); intSort(S, N); add_node(S); rep(k,node){ if(state_sum[k]==0){ ed = k; edge[k][0] = edge[k][1] = -1; continue; } /* end state = there are no ball at all */ /* create edge (S[0], S[1], ..., S[N-1]) -> (S[0], S[1], ..., S[N-1-m]-1, ..., S[N-1]) */ /* where S[0] <= S[1] <= ... <= S[N-1], and (S[0], S[1], ..., S[N-1]) denotes the k-th state (k-th node) */ /* That is, this edge means using the m-th largest color is chosen by Ciel */ rep(m,2){ if(N-1-m < 0 || state[k][N-1-m]==0){ edge[k][m] = -1; continue; } /* There is no such color (ball) */ rep(i,N) S[i] = state[k][i]; S[N-1-m]--; for(i=N-1-m;i;i--) if(S[i] < S[i-1]) j = S[i], S[i] = S[i-1], S[i-1] = j; else break; /* sort S */ edge[k][m] = get_node(S); } } /* end - generate graph */ /* do binary search and DP*/ a = 0; b = 1000000000000000LL; while(a