#include using namespace std; const int N = 1007; const int M = 1007; const int B = 107; mt19937 mt(79); uniform_int_distribution uni1, uni2; int range_random(int lvalue, int rvalue){ uniform_int_distribution uni = uniform_int_distribution(lvalue, rvalue); return uni(mt); } int rnd_sh(int mod){ return range_random(0, mod - 1); } int int_random(int lvalue, int rvalue){ int random_integer; if(lvalue == 0){ random_integer = uni1(mt); } else{ random_integer = uni2(mt); } //cout << lvalue << " " << rvalue << " = " << random_integer << "\n"; return random_integer; } clock_t t; inline bool time_left(double f){ return (bool)((double)(clock() - t) / CLOCKS_PER_SEC <= f); } inline double time_passed(){ return ((double)(clock() - t) / CLOCKS_PER_SEC); } int a[N][M]; int n, m, b; struct solution{ bitset in; int score; int sum[M]; int change[N]; solution(){ score = 0; for(int i = 1; i <= m; i++){ sum[i] = 0; } for(int i = 1; i <= n; i++){ in[i] = int_random(0, 1); if(in[i]){ update_line(i, 1); } } } solution(const bitset &in){ this->in = in; score = 0; for(int i = 1; i <= m; i++){ sum[i] = 0; } for(int i = 1; i <= n; i++){ if(in[i]){ update_line(i, 1); } } } solution mutate(int cnt_it){ solution ret = *this; for(int i = 1; i <= cnt_it; i++){ int idx = int_random(1, n); ret.in[idx] = !ret.in[idx]; if(ret.in[idx]){ ret.update_line(idx, 1); } else{ ret.update_line(idx, -1); } } return ret; } void try_all(){ int pr_score = score; for(int i = 1; i <= n; i++){ in[i] = !in[i]; if(in[i]){ update_line(i, 1); } else{ update_line(i, -1); } if(score < pr_score){ if(in[i]){ update_line(i, -1); } else{ update_line(i, 1); } in[i] = !in[i]; } pr_score = score; } } void update_line(int idx, int mult){ if(mult == 1){ for(int i = 1; i <= m; i++){ int pr_sum = sum[i]; sum[i] += a[idx][i]; if(sum[i] >= b){ sum[i] -= b; } else if(sum[i] < 0){ sum[i] += b; } score += sum[i] * sum[i] - pr_sum * pr_sum; } } else{ for(int i = 1; i <= m; i++){ int pr_sum = sum[i]; sum[i] -= a[idx][i]; if(sum[i] >= b){ sum[i] -= b; } else if(sum[i] < 0){ sum[i] += b; } score += sum[i] * sum[i] - pr_sum * pr_sum; } } } void output(){ int k = 0; for(int i = 1; i <= n; i++){ if(in[i]){ k++; } } cout << k << "\n"; for(int i = 1; i <= n; i++){ if(in[i]){ cout << i << "\n"; } } } friend bool operator<(const solution &lvalue, const solution &rvalue){ return lvalue.score > rvalue.score; } }; solution find_best(int num, vector v, solution sol){ for(int i = 0; i < num; i++){ int idx = v[i]; bool boo = false; if(boo != sol.in[idx]){ sol.in[idx] = boo; if(boo){ sol.update_line(idx, 1); } else{ sol.update_line(idx, -1); } } } solution best = sol; for(int i = 1; i < (1 << num); i++){ for(int j = 0; j < num; j++){ int idx = v[j]; bool boo = (bool)(i & (1 << j)); if(boo != sol.in[idx]){ sol.in[idx] = boo; if(boo){ sol.update_line(idx, 1); } else{ sol.update_line(idx, -1); } } } best = min(best, sol); } return best; } const int CNT_SOL = 10; const int cnt_two = 8; solution s[10]; int arr[N]; int main(){ t = clock(); ios::sync_with_stdio(false); cin.tie(NULL); freopen("subsetselection.in", "r", stdin); freopen("subsetselection.out", "w", stdout); cin >> n >> m >> b; uni1 = uniform_int_distribution(0, 1); uni2 = uniform_int_distribution(1, n); for(int i = 1; i <= n; i++){ for(int j = 1; j <= m; j++){ cin >> a[i][j]; a[i][j] %= b; } } if(n == 20){ vector v; for(int i = 1; i <= n; i++){ v.push_back(i); } solution best; best = find_best(n, v, best); best.output(); return 0; } for(int i = 0; i < CNT_SOL; i++){ s[i].try_all(); } while(time_left(1)){ for(int i = 0; i < CNT_SOL; i++){ s[i] = min(s[i], s[i].mutate(3)); } } vector v; for(int i = 0; i < cnt_two; i++){ v.push_back(0); } for(int i = 1; i <= n; i++){ arr[i] = i; } while(time_left(4.85)){ random_shuffle(arr + 1, arr + n + 1, rnd_sh); for(int j = 1; j + cnt_two < n j += cnt_two){ for(int i = 0; i < cnt_two; i++){ v[i] = arr[i + j]; } for(int i = 0; i < CNT_SOL; i++){ int pr_score = s[i].score; s[i] = find_best(cnt_two, v, s[i]); } } } sort(s, s + CNT_SOL); s[0].output(); return 0; }