int rec(int nodes, bits &curr, bits &pool, bits &excl) { if (pool.none() && excl.none()) { return curr.count(); } int ans = 0, u = 0; for (int v = 0; v < nodes; v++) { if (pool[v] || excl[v]) { u = v; } } for (int v = 0; v < nodes; v++) { if (!pool[v] || adj[u][v]) { continue; } bits ncurr, npool, nexcl; for (int i = 0; i < nodes; i++) { ncurr[i] = curr[i]; } ncurr[v] = true; for (int j = 0; j < nodes; j++) { npool[j] = pool[j] && adj[v][j]; nexcl[j] = excl[j] && adj[v][j]; } ans = std::max(ans, rec(nodes, ncurr, npool, nexcl)); pool[v] = false; excl[v] = true; } return ans; }
void take2(int pos, bits &ret) { ret.set(pos); for(int i=0;i<N-1;i++) { if(rela[i].first == pos && !ret.test(rela[i].second)) { take2(rela[i].second, ret); } if(rela[i].second == pos && !ret.test(rela[i].first)) { take2(rela[i].first, ret); } } }
void take(int pos, int no, bits &ret) { ret.set(pos); for(int i=0;i<N-1;i++) { if(rela[i].first == pos && rela[i].second != no) { take2(rela[i].second, ret); } if(rela[i].second == pos && rela[i].first != no) { take2(rela[i].first, ret); } } ret.reset(pos); }
int go(bits &st) { if(memo.count(st)) { return memo[st]; } bits candi = st; int cnt = candi.count(); if(cnt == 0) return 1; for(int i=0;i<N-1;i++) { int p1 = rela[i].first; int p2 = rela[i].second; if(!st.test(p1) || !st.test(p2)) continue; candi.reset(p2); } long long rett = 0; for(int i=0;i<N;i++) { if(candi.test(i)) { long long ret = 1; int cnt2 = cnt-1; for(int j=0;j<N-1;j++) { if(rela[j].first == i) { bits tmp; take(rela[j].second, i, tmp); tmp.set(rela[j].second); for(int k=0;k<N;k++) { if(tmp.test(k) && !st.test(k)) tmp.reset(k); } int tmp2 = tmp.count(); ret *= combi[cnt2][tmp2]; cnt2 -= tmp2; ret %= 1000000007; ret *= go(tmp); ret %= 1000000007; } } rett += ret; rett %= 1000000007; } } memo[st] = rett; }
static inline bool iddfs(bits state, val const res, val const rem, val const d) { if (rem == 0) return true; if (memed(state)) return false; if (rem > d) return false; num[d] = res; bits was_processed = state; defrd_size[d] = 0; for (val k = d; k <= start_d; ++k) { val const i = num[k]; for (val j = start_d; j > k; --j) { val const rhs = num[j]; val const sum = i + rhs; if (sum <= max_n && process(was_processed, state, sum, rem, d, add, i, rhs)) return true; val const diff = abs(i - rhs); if (process(was_processed, state, diff, rem, d, sub, max(i, rhs), min(i, rhs))) return true; } for (val j = 2*i, p = 1; j <= max_n; j *= 2, ++p) if (process(was_processed, state, j, rem, d, shift, i, p)) return true; } for (val l = 0; l < defrd_size[d]; ++l) { action const &defrd = deferred[d][l]; state.set(defrd.res); if(iddfs(state, defrd.res, rem, d - 1)) { result[d] = defrd; return true; } state.reset(defrd.res); } return false; }
static inline bool process(bits &was_processed, bits state, val const j, val const rem, val const d, char const *const actname, val const lhs, val const rhs) { if (was_processed.test(j)) return false; was_processed.set(j); if (target.test(j)) { state.set(j); if (iddfs(state, j, rem - 1, d - 1)) { result[d].name = actname; result[d].lhs = lhs; result[d].rhs = rhs; return true; } return false; } action &defrd = deferred[d][defrd_size[d]]; defrd.name = actname; defrd.lhs = lhs; defrd.rhs = rhs; defrd.res = j; ++defrd_size[d]; return false; }
static inline bool memed(bits const state) { unsigned long long const i = (state.to_ullong() * 2038074743) % mem_size; bool const already_in = mem[i] == state; mem[i] = state; return already_in; }