#include #include #include #include #include #include #include #include #include using namespace std; constexpr int MAXK = 8; map, int> combinations; void precompute(int k) { set> partitions[2*MAXK - 1]; // partitions[0].insert(vector()); for (int l = 1; l < k; l++) { partitions[l].insert({ l }); } for (int l = 0; l <= 2 * k - 2; l++) { for (vector S : partitions[l]) { for (int x = S.back(); x < k && x + l <= 2 * k - 2; x++) { vector Sp(begin(S), end(S)); Sp.push_back(x); partitions[l + x].insert(Sp); } } } for (int l = k; l <= 2 * k - 2; l++) { for (vector S : partitions[l]) { if (S.back() < l - k) continue; array A = {}; for (int x : S) A[x]++; combinations[A] = l - k; } } } namespace std { template struct hash> { public: size_t operator()(const array &v) const { size_t x = 0; for (const T &t : v) x ^= hash()(t) + 0x9e3779b9 + (x<<6) + (x>>2); return x; } }; } unordered_map, int> memo; int k; int solve(array A) { // Precomputation: remove pairs of two because these match up nice. for (int i = 1; i < k - i; i++) { while (A[i] != 0 && A[k - i] != 0) { A[i]--; A[k - i]--; } } if (k % 2 == 0) A[k/2] &= 1; if (memo.find(A) != memo.end()) return memo[A]; bool is_zero = true; for (int &x : A) if (x != 0) [[likely]] { is_zero = false; break; } if (is_zero) return 0; int res = 100; for (pair, int> subs : combinations) { bool valid = true; for (int l = 1; l < k; l++) if (subs.first[l] > A[l]) { valid = false; break; } if (!valid) continue; array B(A); for (int l = 1; l < k; l++) B[l] -= subs.first[l]; if (subs.second) B[subs.second]++; res = min(res, (subs.second != 0) + solve(B)); } // for (int x : A) cout << x << " "; // cout << "-> " << res << endl; return memo[A] = res; } int main() { int n; cin >> n >> k; assert(k <= 8); precompute(k); vector v(n); for (int &x : v) cin >> x; int res = 0; // res <= 10^8 for (int &x : v) { res += (x - 1) / k; x %= k; } if (k == 1) { cout << res << endl; return 0; } array num_left = {}; for (int x : v) { if (x) num_left[x]++; } for (int l = 1; l + l < k; l++) { int x = min(num_left[l], num_left[k - l]); num_left[l] -= x; num_left[k - l] -= x; } if (k % 2 == 0) { num_left[k/2] &= 1; } cout << res + solve(num_left) << endl; return 0; }