#include <algorithm> #include <cstdio> #include <iostream> #include <vector> using namespace std; int n; void Fill(vector<int>::const_iterator ai, vector<bool>::iterator vi, const int size, const int capacity) { if (capacity < 0) return; if (size == 1) { *vi = true; return; } Fill(ai + 1, vi , size / 2, capacity ); Fill(ai + 1, vi + size / 2, size / 2, capacity - *ai); } void ExtractGenerators(const vector<bool> &v, vector<int> *ret) { // cerr << "Building generator list." << endl; ret->clear(); vector<bool> generated(1 << n, false); for (int i = (1 << n) - 1; i >= 0; --i) { if (v[i] && !generated[i]) { // cerr << "Generator " << i << endl; ret->push_back(i); generated[i] = true; } if (generated[i]) { int src = n - 1; int dst = n - 1; while (src >= 0) { const int src_mask = 1 << src; if (i & src_mask) { while (dst >= src) --dst; while (dst >= 0 && (i & (1 << dst))) --dst; int j = i & ~src_mask; if (dst >= 0) j |= 1 << dst; generated[j] = true; } --src; } } } } void ComputeGenerators(const int c, const vector<int> &a, vector<int> *ret) { vector<bool> v(1 << n, false); Fill(a.begin(), v.begin(), 1 << n, c); // cerr << "Fill complete." << endl; ExtractGenerators(v, ret); } void ComputeProduct(const vector<int> &v1, const vector<int> &v2, vector<bool> *b) { for (int i = 0; i < v1.size(); ++i) for (int j = 0; j < v2.size(); ++j) { int k = v2[j]; int mask = 1 << (n - 1); int count = 0; while (mask) { if (v1[i] & mask) ++count; if (count) if (!(k & mask)) { k |= mask; --count; } mask >>= 1; } (*b)[k] = true; } } int main() { int m; scanf("%d%d", &n, &m); vector<int> a(n); for (int i = 0; i < n; ++i) scanf("%d", &a[i]); sort(a.rbegin(), a.rend()); vector<int> c(m); for (int i = 0; i < m; ++i) scanf("%d", &c[i]); sort(c.rbegin(), c.rend()); if (m > n) { m = n; c.resize(m); } vector<int> all(1, 0); int ret = 0; while (ret < m && all[0] + 1 != 1 << n) { // cerr << all[0] << ' ' << ret << endl; vector<int> current; ComputeGenerators(c[ret++], a, ¤t); // cerr << "Current computed." << endl; vector<bool> next(1 << n, false); ComputeProduct(all, current, &next); ExtractGenerators(next, &all); } if (all[0] + 1 == 1 << n) { printf("%d\n", ret); } else { printf("NIE\n"); } return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | #include <algorithm> #include <cstdio> #include <iostream> #include <vector> using namespace std; int n; void Fill(vector<int>::const_iterator ai, vector<bool>::iterator vi, const int size, const int capacity) { if (capacity < 0) return; if (size == 1) { *vi = true; return; } Fill(ai + 1, vi , size / 2, capacity ); Fill(ai + 1, vi + size / 2, size / 2, capacity - *ai); } void ExtractGenerators(const vector<bool> &v, vector<int> *ret) { // cerr << "Building generator list." << endl; ret->clear(); vector<bool> generated(1 << n, false); for (int i = (1 << n) - 1; i >= 0; --i) { if (v[i] && !generated[i]) { // cerr << "Generator " << i << endl; ret->push_back(i); generated[i] = true; } if (generated[i]) { int src = n - 1; int dst = n - 1; while (src >= 0) { const int src_mask = 1 << src; if (i & src_mask) { while (dst >= src) --dst; while (dst >= 0 && (i & (1 << dst))) --dst; int j = i & ~src_mask; if (dst >= 0) j |= 1 << dst; generated[j] = true; } --src; } } } } void ComputeGenerators(const int c, const vector<int> &a, vector<int> *ret) { vector<bool> v(1 << n, false); Fill(a.begin(), v.begin(), 1 << n, c); // cerr << "Fill complete." << endl; ExtractGenerators(v, ret); } void ComputeProduct(const vector<int> &v1, const vector<int> &v2, vector<bool> *b) { for (int i = 0; i < v1.size(); ++i) for (int j = 0; j < v2.size(); ++j) { int k = v2[j]; int mask = 1 << (n - 1); int count = 0; while (mask) { if (v1[i] & mask) ++count; if (count) if (!(k & mask)) { k |= mask; --count; } mask >>= 1; } (*b)[k] = true; } } int main() { int m; scanf("%d%d", &n, &m); vector<int> a(n); for (int i = 0; i < n; ++i) scanf("%d", &a[i]); sort(a.rbegin(), a.rend()); vector<int> c(m); for (int i = 0; i < m; ++i) scanf("%d", &c[i]); sort(c.rbegin(), c.rend()); if (m > n) { m = n; c.resize(m); } vector<int> all(1, 0); int ret = 0; while (ret < m && all[0] + 1 != 1 << n) { // cerr << all[0] << ' ' << ret << endl; vector<int> current; ComputeGenerators(c[ret++], a, ¤t); // cerr << "Current computed." << endl; vector<bool> next(1 << n, false); ComputeProduct(all, current, &next); ExtractGenerators(next, &all); } if (all[0] + 1 == 1 << n) { printf("%d\n", ret); } else { printf("NIE\n"); } return 0; } |