// This takes one group summing to 0 at a time. // Note that groups >k are excluded, because those always contain a smaller // group summing to k. #include #include #include #include #include using namespace std; // Tuples that can be removed. The inner vector has size k. vector> zeros; void init_zeros(int k) { for(int i1 = 0; i1 <= k && (i1 < 1 || k > 1); ++i1) { for(int i2 = 0; i1 + i2 <= k && (i2 < 1 || k > 2); ++i2) { for(int i3 = 0; i1 + i2 + i3 <= k && (i3 < 1 || k > 3); ++i3) { for(int i4 = 0; i1 + i2 + i3 + i4 <= k && (i4 < 1 || k > 4); ++i4) { for(int i5 = 0; i1 + i2 + i3 + i4 + i5 <= k && (i5 < 1 || k > 5); ++i5) { for(int i6 = 0; i1 + i2 + i3 + i4 + i5 + i6 <= k && (i6 < 1 || k > 6); ++i6) { for(int i7 = 0; i1 + i2 + i3 + i4 + i5 + i6 + i7 <= k && (i7 < 1 || k > 7); ++i7) { int s = 1 * i1 + 2 * i2 + 3 * i3 + 4 * i4 + 5 * i5 + 6 * i6 + 7 * i7; if(s > 0 && s % k == 0) { zeros.push_back({0, i1, i2, i3, i4, i5, i6, i7}); } } } } } } } } } map, int> cache; int k; int solve(vector& v) { if(cache.contains(v)) { return cache[v]; } int best = -1; for(auto& cnt : zeros) { bool ok = true; for(int j = 1; j < k; ++j) ok &= cnt[j] <= v[j]; if(!ok) continue; for(int j = 1; j < k; ++j) v[j] -= cnt[j]; best = max(best, 1 + solve(v)); for(int j = 1; j < k; ++j) v[j] += cnt[j]; } assert(best >= 1); return cache[v] = best; } int main() { int n; cin >> n >> k; int sum = 0; vector cnt(k); int ans = 0; for(int i = 0; i < n; ++i) { int x; cin >> x; sum += x; if(x % k == 0) { ++ans; } else { cnt[x % k] += 1; } } // opposite pairs for(int i = 1; 2 * i < k; ++i) { auto x = min(cnt[i], cnt[k - i]); cnt[i] -= x; cnt[k - i] -= x; ans += x; } if(k % 2 == 0) { ans += cnt[k / 2] / 2; cnt[k / 2] %= 2; } init_zeros(k); cache[vector(k, 0)] = 0; cout << sum / k - ans - solve(cnt) << endl; }