#include #define endl '\n' #define TRACE(x) cerr << #x << " = " << x << endl //#define LOCAL using namespace std; template inline bool chkmax(T &x, const T1 &y) { return x < y ? x = y, true : false; } template inline bool chkmin(T &x, const T1 &y) { return x > y ? x = y, true : false; } const int MAXN = 1024; const int MAXM = 1024; int m, b; struct sequence { int seq[MAXM]; void read() { for (int i = 0; i < m; i++) cin >> this->seq[i]; } sequence operator +(const sequence &other) const { sequence ans; for (int i = 0; i < m; i++) ans.seq[i] = (this->seq[i] + other.seq[i]) % b; return ans; } sequence& operator +=(const sequence &other) { for (int i = 0; i < m; i++) this->seq[i] = (this->seq[i] + other.seq[i]) % b; return *this; } int get_sum() const { int ans = 0; for (int i = 0; i < m; i++) ans += this->seq[i] * this->seq[i]; return ans; } }; ostream& operator <<(ostream &os, const sequence &seq) { for (int i = 0; i < m; i++) os << seq.seq[i] << ' '; return os; } int n; sequence a[MAXN]; void read() { cin >> n >> m >> b; for (int i = 0; i < n; i++) a[i].read(); } int dp[MAXN]; int parent[MAXN]; sequence sum_sequences[MAXN]; void brute_force() { int best_mask = 0, best_sum = 0; sequence help; for (int mask = 1; mask < (1 << n); mask++) { for (int i = 0; i < m; i++) help.seq[i] = 0; for (int rmask = mask, idx = 0; rmask; rmask >>= 1, idx++) { if (rmask & 1) help = help + a[idx]; } if (chkmax(best_sum, help.get_sum())) best_mask = mask; } cout << __builtin_popcount(best_mask) << endl; for (int idx = 1; best_mask; best_mask >>= 1, idx++) { if (best_mask & 1) cout << idx << endl; } } void smart_brute_force() { int best_mask = 0, best_sum = 0, best_offset; sequence help; int jump = n >= 20 ? n / 20 : n; for (int mask = 1; mask < (1 << 14); mask++) { for (int offset = 0; offset < n; offset += jump) { for (int i = 0; i < m; i++) help.seq[i] = 0; for (int rmask = mask, idx = offset; rmask; rmask >>= 1, idx++) { if (rmask & 1) help = help + a[idx]; } if (chkmax(best_sum, help.get_sum())) { best_mask = mask; best_offset = offset; } } } cout << __builtin_popcount(best_mask) << endl; for (int idx = best_offset; best_mask; best_mask >>= 1, idx++) { if (best_mask & 1) cout << (idx + 1) << endl; } } void solve() { if (n <= 20) { brute_force(); return; } if (n <= 200) { smart_brute_force(); return; } dp[0] = a[0].get_sum(); parent[0] = -1; sum_sequences[0] = a[0]; sequence help; int max_idx = 0, max_dp = dp[0]; for (int i = 1; i < n; i++) { int parent_idx = -1; int max_sum = 0; sequence max_seq; for (int j = i - 1; j >= 0; j--) { help = sum_sequences[j] + a[i]; if (chkmax(max_sum, help.get_sum())) { parent_idx = j; max_seq = help; } } dp[i] = max_sum; parent[i] = parent_idx; sum_sequences[i] = max_seq; if (chkmax(dp[i], a[i].get_sum())) { parent[i] = -1; sum_sequences[i] = a[i]; } if (chkmax(max_dp, dp[i])) max_idx = i; /* TRACE(i); TRACE(dp[i]); TRACE(parent[i]); cerr << sum_sequences[i] << endl; */ } vector ans; int curr = max_idx; while (curr != -1) { ans.push_back(curr); curr = parent[curr]; } cout << ans.size() << endl; for (int idx : ans) cout << (idx + 1) << endl; } int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); #ifndef LOCAL freopen("subsetselection.in", "rt", stdin); freopen("subsetselection.out", "wt", stdout); #endif // LOCAL read(); solve(); return EXIT_SUCCESS; }