// This takes one group summing to 0 at a time, and only considers groups with counts at most the // number of available stones. #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, vector& cnt) { cnt.resize(8, 0); for(int i1 = 0; i1 <= k && i1 <= cnt[1]; ++i1) { for(int i2 = 0; i1 + i2 <= k && i2 <= cnt[2]; ++i2) { for(int i3 = 0; i1 + i2 + i3 <= k && i3 <= cnt[3]; ++i3) { for(int i4 = 0; i1 + i2 + i3 + i4 <= k && i4 <= cnt[4]; ++i4) { for(int i5 = 0; i1 + i2 + i3 + i4 + i5 <= k && i5 <= cnt[5]; ++i5) { for(int i6 = 0; i1 + i2 + i3 + i4 + i5 + i6 <= k && i6 <= cnt[6]; ++i6) { for(int i7 = 0; i1 + i2 + i3 + i4 + i5 + i6 + i7 <= k && i7 <= cnt[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}); } } } } } } } } cnt.resize(k); } 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, cnt); cache[vector(k, 0)] = 0; cout << sum / k - ans - solve(cnt) << endl; }