Problem:
Sum Source Detection
JAG members began a game with integers. The game consists of $N + M + 1$ players: $N$ open number holders, $M$ secret number holders, and one answerer, you.
In the preparation, an integer $K$ is told to all $N + M + 1$ players. $N + M$ number holders choose their own integers per person under the following restrictions:
Each holder owns a positive integer.
The sum of all the integers equals $K$.
Every integer owned by secret number holders is strictly less than any integers owned by open number holders.
After the choices, $N$ open number holders show their integers $O_1, ..., O_N$ to the answerer while secret number holders do not.
The game has $Q$ rounds. At the beginning of each round, $M$ secret number holders can change their numbers under
the above restrictions, while open number holders cannot. Then $N + M$ number holders select part of members among
them arbitrary, calculate the sum $X$ of the integers owned by the selected members, and tell $X$ to the answerer. For
each round, the answerer tries to identify the definitely selected open number holders from the information $K$, $X$, and $O_1, ..., O_N$: The answerer will get points per actually selected open number holder in the answer. On the other hand, if the answer contains at least one non-selected member, you lose your points got in the round. Thus, the answerer, you, must answer only the open number holders such that the holders are definitely selected.
Your task in this problem is to write a program to determine all the open number holders whose integers are necessary to the sum for each round in order to maximize your points.
Input
The input consists of a single test case formatted as follows.
$N$ $M$ $K$ $Q$
$O_1$ ... $O_N$
$X_1$ ... $X_Q$
The first line consists of four integers $N, M, K,$ and $Q$. $N$ and $M$ are the numbers of open number holders and secret number holders respectively ($1 \leq N, 0 \leq M, N + M \leq 40$). $K$ is an integer ($1 \leq K \leq 200,000$). $Q$ is the number of rounds of the game ($1 \leq Q \leq 10,000$).
The second line contains $N$ integers $O_1, ..., O_N$, as the $i$-th open number holder owns $O_i$ ($1 \leq O_1 \leq ... \leq O_N \leq K$).
The third line indicates $Q$ integers $X_1, ..., X_Q$ ($0 \leq X_i \leq K$). $X_i$ is the sum of the integers owned by the selected members in the $i$-th round.
It is guaranteed that there is at least one way to compose $X_i$. In other words, you can assume that there is at least one integer sequence $S_1, ..., S_M$, which represents integers owned by secret number holders, satisfying the followings:
$0 < S_j < O_1$ for $1 \leq j \leq M$. Note that $O_1 = min_{1\leq k \leq N}O_k$ holds.
$\sum_{j=1}^N O_j + \sum_{k=1}^M S_k = K$.
There is at least one pair of subsets $U \subseteq \{1,...,N\}$ and $V \subseteq \{1, ..., M\}$ such that $\sum_{j\in U} O_j + \sum_{k\in V}S_k = X_i$ holds.
Output
On each sum $X_i$, print the indices of the open number holders whose integers are required to make up 
...(truncated)

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=998244353,MAX=300005,INF=15<<26;
bool can[MAX];
bool dp[43][MAX];

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    ll N,M,K,Q;cin>>N>>M>>K>>Q;
    vector<ll> O(N);
    ll lim=INF,sum=K;
    for(int i=0;i<N;i++){
        cin>>O[i];
        chmin(lim,O[i]-1);
        sum-=O[i];
    }
    
    for(ll k=0;k<=M;k++){
        for(ll S=0;S<=K;S++){
            if(k<=S&&S<=k*lim&&(M-k)<=sum-S&&sum-S<=(M-k)*lim){
                can[S]=true;
                //cout<<S<<endl;
            }
        }
    }
    for(int i=0;i<N;i++){
        for(int S=0;S<=K;S++) dp[i][S]=can[S];
        for(int j=0;j<N;j++){
            if(i==j) continue;
            for(int S=K;S>=O[j];S--) dp[i][S]|=dp[i][S-O[j]];
        }
    }
    
    while(Q--){
        ll x;cin>>x;
        vector<int> ans;
        
        for(int i=0;i<N;i++){
            if(!dp[i][x]) ans.push_back(i);
        }
        
        if(si(ans)==0) cout<<-1<<"\n";
        else{
            for(int i=0;i<si(ans);i++){
                if(i) cout<<" ";
                cout<<ans[i]+1;
            }
            cout<<"\n";
        }
    }
}
accuracy: 1
time_ms: 100
memory_kb: 15096
final_rank: 1

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 200005

int N,M,K,num_query;
int O[45],X[10005];
bool secret_table[SIZE],can_make[SIZE];
bool dp[45][SIZE],without[45][SIZE];


int main(){

	scanf("%d %d %d %d",&N,&M,&K,&num_query);

	scanf("%d",&O[0]);
	int tmp_sum = O[0];
	int secret_max = O[0]-1;

	for(int i = 1; i < N; i++){

		scanf("%d",&O[i]);
		tmp_sum += O[i];
	}

	for(int i = 0; i < num_query; i++){

		scanf("%d",&X[i]);
	}

	int secret_total = K-tmp_sum;
	if(secret_max == 0 && M > 0){ //制約に反する

		for(int i = 0; i < num_query; i++){
			printf("-1\n");
		}
		return 0;
	}

	for(int i = 0; i <= N; i++){
		for(int sum = 0; sum <= K; sum++){

			dp[i][sum] = false; //dp[openを何個目まで見たか][合計] = 作れるかどうか
		}
	}


	//secret集合で数iが作れるか
	for(int i = 0; i <= secret_total; i++){

		secret_table[i] = false;
	}

	//数iを作れるかどうか
	for(int i = 0; i <= K; i++){

		can_make[i] = false;
	}

	if(secret_max == 0){ //M == 0

		secret_table[0] = true;
		can_make[0] = true;
		dp[0][0] = true;

	}else{

		//secret集合で部分和を作れるか調べる
		for(int S = 0; S <= secret_total; S++){

			int tmp = S/secret_max;
			if(S%secret_max != 0){

				tmp++;
			}
			if(secret_max*(M-tmp)+S >= secret_total){

				secret_table[S] = true;
				can_make[S] = true;
				dp[0][S] = true;
			}
		}
	}

	//作れる数を調べる
	for(int i = 1; i <= N; i++){
		for(int pre_sum = 0; pre_sum <= K; pre_sum++){
			if(!dp[i-1][pre_sum])continue;

			dp[i][pre_sum] = true; //O[i-1]を使わない

			if(pre_sum+O[i-1] <= K){
				dp[i][pre_sum+O[i-1]] = true;
				can_make[pre_sum+O[i-1]] = true;
			}
		}
	}

	//O[i-1]を使わずにsumが作れるか調べる
	for(int i = 0; i <= N; i++){
		for(int sum = 0; sum <= K; sum++){

			without[i][sum] = false; //sumが作れるならtrue
		}
	}

	for(int dont_use = 1; dont_use <= N; dont_use++){
		for(int i = 0; i <= N; i++){
			for(int sum = 0; sum <= K; sum++){

				dp[i][sum] = false;
			}
		}
		//secretの結果を反映
		for(int i = 0; i <= secret_total; i++){

			dp[0][i] = secret_table[i];
			without[dont_use][i] = secret_table[i];
		}

		for(int i = 1; i <= N; i++){
			for(int pre_sum = 0; pre_sum <= K; pre_sum++){
				if(!dp[i-1][pre_sum])continue;

				dp[i][pre_sum] = true; //O[i-1]を使わない

				if(i == dont_use)continue;

				if(pre_sum+O[i-1] <= K){

					dp[i][pre_sum+O[i-1]] = true;
					without[dont_use][pre_sum+O[i-1]] = true;
				}
			}
		}
	}

	vector<int> V;

	for(int loop = 0; loop < num_query; loop++){

		if(!can_make[X[loop]]){

			printf("-1\n");
			continue;
		}

		V.clear();

		for(int i = 1; i <= N; i++){

			if(!without[i][X[loop]]){

				V.push_back(i);
			}
		}

		if(V.size() == 0){

			printf("-1\n");
			continue;
		}

		printf("%d",V[0]);
		for(int i = 1; i < V.size(); i++){

			printf(" %d",V[i]);
		}
		printf("\n");
	}

	return 0;
}
accuracy: 1
time_ms: 260
memory_kb: 19532
final_rank: 3

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 200005

int N,M,K,num_query;
int O[45],X[10005];
bool secret_table[SIZE],can_make[SIZE];
bool dp[45][SIZE],without[45][SIZE];


int main(){

	scanf("%d %d %d %d",&N,&M,&K,&num_query);

	scanf("%d",&O[0]);
	int tmp_sum = O[0];
	int secret_max = O[0]-1;

	for(int i = 1; i < N; i++){

		scanf("%d",&O[i]);
		tmp_sum += O[i];
	}

	for(int i = 0; i < num_query; i++){

		scanf("%d",&X[i]);
	}

	int secret_total = K-tmp_sum;
	if(secret_max == 0 && M > 0){ //制約に反する

		for(int i = 0; i < num_query; i++){
			printf("-1\n");
		}
		return 0;
	}

	for(int i = 0; i <= N; i++){
		for(int sum = 0; sum <= K; sum++){

			dp[i][sum] = false; //dp[openを何個目まで見たか][合計] = 作れるかどうか
		}
	}


	//secret集合で数iが作れるか
	for(int i = 0; i <= secret_total; i++){

		secret_table[i] = false;
	}

	//数iを作れるかどうか
	for(int i = 0; i <= K; i++){

		can_make[i] = false;
	}

	if(secret_max == 0){ //M == 0

		secret_table[0] = true;
		can_make[0] = true;
		dp[0][0] = true;

	}else{

		//secret集合で部分和を作れるか調べる
		for(int S = 0; S <= secret_total; S++){

			int tmp = S/secret_max;
			if(S%secret_max != 0){

				tmp++;
			}
			if(secret_max*(M-tmp)+S >= secret_total){

				secret_table[S] = true;
				can_make[S] = true;
				dp[0][S] = true;
			}
		}
	}

	for(int i = 1; i <= N; i++){
		for(int pre_sum = 0; pre_sum <= K; pre_sum++){
			if(!dp[i-1][pre_sum])continue;

			dp[i][pre_sum] = true; //O[i-1]を使わない

			if(pre_sum+O[i-1] <= K){
				dp[i][pre_sum+O[i-1]] = true;
				can_make[pre_sum+O[i-1]] = true;
			}
		}
	}

	//O[i-1]を使わずにsumが作れるか調べる
	for(int i = 0; i <= N; i++){
		for(int sum = 0; sum <= K; sum++){

			without[i][sum] = false; //sumが、少なくとも1つopenを含み、かつ作れるならtrue
		}
	}

	for(int dont_use = 1; dont_use <= N; dont_use++){
		for(int i = 0; i <= N; i++){
			for(int sum = 0; sum <= K; sum++){

				dp[i][sum] = false;
			}
		}
		//secretの結果を反映
		for(int i = 0; i <= secret_total; i++){

			dp[0][i] = secret_table[i];
			without[dont_use][i] = secret_table[i];
		}

		for(int i = 1; i <= N; i++){
			for(int pre_sum = 0; pre_sum <= K; pre_sum++){
				if(!dp[i-1][pre_sum])continue;

				dp[i][pre_sum] = true; //O[i-1]を使わない

				if(i == dont_use)continue;

				if(pre_sum+O[i-1] <= K){

					dp[i][pre_sum+O[i-1]] = true;
					without[dont_use][pre_sum+O[i-1]] = true;
				}
			}
		}
	}

	vector<int> V;

	for(int loop = 0; loop < num_query; loop++){

		if(!can_make[X[loop]]){

			printf("-1\n");
			continue;
		}

		V.clear();

		for(int i = 1; i <= N; i++){

			if(!without[i][X[loop]]){

				V.push_back(i);
			}
		}

		if(V.size() == 0){

			printf("-1\n");
			continue;
		}

		printf("%d",V[0]);
		for(int i = 1; i < V.size(); i++){

			printf(" %d",V[i]);
		}
		printf("\n");
	}

	return 0;
}
accuracy: 1
time_ms: 260
memory_kb: 19532
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    int i, j;
    int n, m, k, q;
    cin >> n >> m >> k >> q;
    int o[n];
    int mi = 1010101010;
    for (i = 0; i < n; i++) {
        cin >> o[i];
        k -= o[i];
        mi = min(mi, o[i]);
    }
    mi--;
    int x[q];
    for (i = 0; i < q; i++) cin >> x[i];

    vector<bool> v(200020, 0);

    if (m != 0) {
        for (i = 0; i < 200020; i++) {
            if (i > k) break;
            int rest = m - i / mi;
            if (i % mi != 0) rest--;
            if (mi * rest + i >= k) v[i] = 1;
        }
    }

    else {
        v[0] = 1;
    }

    vector<vector<bool> > w(n);
    for (i = 0; i < n; i++) w[i] = v;

    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            if (i == j) continue;
            for (int l = 200019; l >= 0; l--) {
                if (l - o[j] >= 0 && w[i][l - o[j]] == 1) w[i][l] = 1;
            }
        }
    }

    for (i = 0; i < q; i++) {
        vector<int> ans;
        for (j = 0; j < n; j++) {
            if (!w[j][x[i]]) ans.push_back(j);
        }
        if (ans.size() == 0) {
            cout << -1 << endl;
        } else {
            for (int a = 0; a < ans.size(); a++) {
                cout << ans[a] + 1;
                if (a != ans.size() - 1) cout << ' ';
            }
            cout << endl;
        }
    }
}
accuracy: 1
time_ms: 310
memory_kb: 3920
final_rank: 2