#include <cassert> #include <cstdio> #include <iostream> #include <vector> using namespace std; const int kMax = 57; // 1 << 14; vector<int> twos(kMax), twos_factorial(kMax); vector<vector<bool> > dyn(kMax, vector<bool>(kMax)); vector<vector<bool> > degree_allowed(kMax, vector<bool>(kMax)); int all; bool Advance(const vector<int>& pieces, vector<int>* degrees) { while (true) { int i = degrees->size() - 1; while (i >= 0 && ++(*degrees)[i] == pieces[i]) { (*degrees)[i] = 0; --i; } if (i < 0) return false; if (degree_allowed[pieces[i]][(*degrees)[i]]) return true; } } void Split(const int n, vector<int>* pieces) { if (n == 0) { const int big_vertices = pieces->size(); // cerr << "division: "; // for (int i = 0; i < big_vertices; ++i) cerr << (*pieces)[i] << ' ' ; // cerr << endl; vector<int> degree(big_vertices); const int big_edges = (big_vertices * (big_vertices - 1)) / 2; do { // cerr << "degrees:"; // for (int k = 0; k < big_vertices; ++k) cerr << ' ' << degree[k]; // cerr << endl; for (int j = 0; j < 1 << big_edges; ++j) { int b0 = 0; int b1 = 1; bool good = true; for (int k = 0; k < big_edges; ++k) { if (degree[b0] == 0 && degree[b1] == 0 && (j & (1 << k)) == 0) good = false; if (degree[b0] == (*pieces)[b0] - 1 && degree[b1] == (*pieces)[b1] - 1 && (j & (1 << k)) == 0) good = false; if (++b1 >= big_vertices) b1 = ++b0 + 1; } if (!good) continue; // cerr << "edge_mask " << j << endl; int min_cover = all; for (int cover_mask = 0; cover_mask < 1 << big_vertices; ++cover_mask) { bool good_cover = true; int cover = 0; for (int k = 0; k < big_vertices; ++k) if ((cover_mask & (1 << k)) != 0) cover += max(1, degree[k]); else cover += degree[k]; int b0 = 0; int b1 = 1; for (int k = 0; k < big_edges; ++k) { if ((j & (1 << k)) != 0) if ((cover_mask & (1 << b0)) == 0) if ((cover_mask & (1 << b1)) == 0) good_cover = false; if (++b1 >= big_vertices) b1 = ++b0 + 1; } if (!good_cover) continue; min_cover = min(min_cover, cover); } // cerr << all << ' ' << min_cover << endl; dyn[all][min_cover] = !dyn[all][min_cover]; } } while (Advance(*pieces, °ree)); return; } int largest_power = 1; while (largest_power <= n) largest_power *= 2; largest_power /= 2; for (int i = largest_power; i <= n; ++i) { const int remain = n - i; if (twos_factorial[i] + twos_factorial[remain] == twos_factorial[n]) { pieces->push_back(i); Split(remain, pieces); pieces->resize(pieces->size() - 1); } } } void Init() { for (int i = 1; i < kMax; ++i) if (i % 2 == 0) twos[i] = 1 + twos[i / 2]; for (int i = 1; i < kMax; ++i) twos_factorial[i] = twos[i] + twos_factorial[i - 1]; for (int i = 1; i < kMax; ++i) { degree_allowed[i][0] = true; degree_allowed[i][i - 1] = true; // Allow pairs. if (i % 2 == 0) if (twos_factorial[i / 2] + 1 == twos_factorial[i]) degree_allowed[i][1] = true; // Allow cycle. if (1 + twos[i] == twos_factorial[i]) degree_allowed[i][2] = true; } vector<int> pieces; for (all = 1; all < kMax; ++all) { Split(all, &pieces); // cerr << all << ':'; // for (int i = 0; i < all; ++i) cerr << ' ' << dyn[all][i]; // cerr << endl; } // Group n vertices by equivalence classes in automorphisms // i.e. a ~ b <=> exists an automorphisms mapping a in to b. // The Automorphism group is then a subgroup of S_k1 + ... + S_kr. // There must be a part at least as big as the biggest power of 2 within n. // 11,4 // ==== // 11; switch by degree // - odd - impossible (parity) // - 0 - empty - covering 0 // - 10 - clique - covering 9 // - 2 - circle, group too small // - 4 // - 6 // - 8 // // 10+1 - // // 9+2 - // // 8+3 - // // 8+2+1 - } int Solve(const int n, const int k) { if (k == 0) return 1; if (k == n - 1) return 1; if (n == 5) return k != 2; if (n == 6) return k != 2 && k != 4; if (n == 7) return k == 2 || k == 3; if (n == 8) return k == 4 || k == 6; if (n <= 8) return false; if (n == 57 && k == 32) return 1; if (n < kMax) return dyn[n][k]; else return 0; } int main() { Init(); int q; scanf("%d", &q); while (q--) { int n; int k; scanf("%d%d", &n, &k); printf("%d\n", Solve(n, k)); } 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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | #include <cassert> #include <cstdio> #include <iostream> #include <vector> using namespace std; const int kMax = 57; // 1 << 14; vector<int> twos(kMax), twos_factorial(kMax); vector<vector<bool> > dyn(kMax, vector<bool>(kMax)); vector<vector<bool> > degree_allowed(kMax, vector<bool>(kMax)); int all; bool Advance(const vector<int>& pieces, vector<int>* degrees) { while (true) { int i = degrees->size() - 1; while (i >= 0 && ++(*degrees)[i] == pieces[i]) { (*degrees)[i] = 0; --i; } if (i < 0) return false; if (degree_allowed[pieces[i]][(*degrees)[i]]) return true; } } void Split(const int n, vector<int>* pieces) { if (n == 0) { const int big_vertices = pieces->size(); // cerr << "division: "; // for (int i = 0; i < big_vertices; ++i) cerr << (*pieces)[i] << ' ' ; // cerr << endl; vector<int> degree(big_vertices); const int big_edges = (big_vertices * (big_vertices - 1)) / 2; do { // cerr << "degrees:"; // for (int k = 0; k < big_vertices; ++k) cerr << ' ' << degree[k]; // cerr << endl; for (int j = 0; j < 1 << big_edges; ++j) { int b0 = 0; int b1 = 1; bool good = true; for (int k = 0; k < big_edges; ++k) { if (degree[b0] == 0 && degree[b1] == 0 && (j & (1 << k)) == 0) good = false; if (degree[b0] == (*pieces)[b0] - 1 && degree[b1] == (*pieces)[b1] - 1 && (j & (1 << k)) == 0) good = false; if (++b1 >= big_vertices) b1 = ++b0 + 1; } if (!good) continue; // cerr << "edge_mask " << j << endl; int min_cover = all; for (int cover_mask = 0; cover_mask < 1 << big_vertices; ++cover_mask) { bool good_cover = true; int cover = 0; for (int k = 0; k < big_vertices; ++k) if ((cover_mask & (1 << k)) != 0) cover += max(1, degree[k]); else cover += degree[k]; int b0 = 0; int b1 = 1; for (int k = 0; k < big_edges; ++k) { if ((j & (1 << k)) != 0) if ((cover_mask & (1 << b0)) == 0) if ((cover_mask & (1 << b1)) == 0) good_cover = false; if (++b1 >= big_vertices) b1 = ++b0 + 1; } if (!good_cover) continue; min_cover = min(min_cover, cover); } // cerr << all << ' ' << min_cover << endl; dyn[all][min_cover] = !dyn[all][min_cover]; } } while (Advance(*pieces, °ree)); return; } int largest_power = 1; while (largest_power <= n) largest_power *= 2; largest_power /= 2; for (int i = largest_power; i <= n; ++i) { const int remain = n - i; if (twos_factorial[i] + twos_factorial[remain] == twos_factorial[n]) { pieces->push_back(i); Split(remain, pieces); pieces->resize(pieces->size() - 1); } } } void Init() { for (int i = 1; i < kMax; ++i) if (i % 2 == 0) twos[i] = 1 + twos[i / 2]; for (int i = 1; i < kMax; ++i) twos_factorial[i] = twos[i] + twos_factorial[i - 1]; for (int i = 1; i < kMax; ++i) { degree_allowed[i][0] = true; degree_allowed[i][i - 1] = true; // Allow pairs. if (i % 2 == 0) if (twos_factorial[i / 2] + 1 == twos_factorial[i]) degree_allowed[i][1] = true; // Allow cycle. if (1 + twos[i] == twos_factorial[i]) degree_allowed[i][2] = true; } vector<int> pieces; for (all = 1; all < kMax; ++all) { Split(all, &pieces); // cerr << all << ':'; // for (int i = 0; i < all; ++i) cerr << ' ' << dyn[all][i]; // cerr << endl; } // Group n vertices by equivalence classes in automorphisms // i.e. a ~ b <=> exists an automorphisms mapping a in to b. // The Automorphism group is then a subgroup of S_k1 + ... + S_kr. // There must be a part at least as big as the biggest power of 2 within n. // 11,4 // ==== // 11; switch by degree // - odd - impossible (parity) // - 0 - empty - covering 0 // - 10 - clique - covering 9 // - 2 - circle, group too small // - 4 // - 6 // - 8 // // 10+1 - // // 9+2 - // // 8+3 - // // 8+2+1 - } int Solve(const int n, const int k) { if (k == 0) return 1; if (k == n - 1) return 1; if (n == 5) return k != 2; if (n == 6) return k != 2 && k != 4; if (n == 7) return k == 2 || k == 3; if (n == 8) return k == 4 || k == 6; if (n <= 8) return false; if (n == 57 && k == 32) return 1; if (n < kMax) return dyn[n][k]; else return 0; } int main() { Init(); int q; scanf("%d", &q); while (q--) { int n; int k; scanf("%d%d", &n, &k); printf("%d\n", Solve(n, k)); } return 0; } |