【LOJ】#2536. 「CQOI2018」解鎖螢幕
阿新 • • 發佈:2018-12-08
題解
什麼破題,看一眼就能想出來\(n^2 2^n\)看了一眼資料範圍有點虛,結果跑得飛快= =
處理出\(a[i][j]\)表示從\(i\)到\(j\)經過的點的點集
然後\(f[i][S]\)表示最後一個點在\(i\)處,經過的點集為\(S\),方案數是多少
然後列舉一個不在\(S\)中的點\(j\)看看\(a[i][j]\)是否全部被\(S\)包含即可
程式碼
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int, int> #define pdi pair<db, int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 1000005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template <class T> void read(T &res) { res = 0; char c = getchar(); T f = 1; while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); } while (c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template <class T> void out(T x) { if (x < 0) { x = -x; putchar('-'); } if (x >= 10) { out(x / 10); } putchar('0' + x % 10); } const int MOD = 100000007; int N, pos[(1 << 20) + 5]; int a[25][25]; int f[21][(1 << 20) + 5], cnt[(1 << 20) + 5]; struct Point { int x, y; Point(int _x = 0, int _y = 0) { x = _x; y = _y; } friend Point operator+(const Point &a, const Point &b) { return Point(a.x + b.x, a.y + b.y); } friend Point operator-(const Point &a, const Point &b) { return Point(a.x - b.x, a.y - b.y); } friend int operator*(const Point &a, const Point &b) { return a.x * b.y - a.y * b.x; } friend int dot(const Point &a, const Point &b) { return a.x * b.x + a.y * b.y; } int norm() { return x * x + y * y; } } P[25]; int inc(int a, int b) { return a + b >= MOD ? a + b - MOD : a + b; } int mul(int a, int b) { return 1LL * a * b % MOD; } int lowbit(int x) { return x & (-x); } void update(int &x, int y) { x = inc(x, y); } void Solve() { read(N); for (int i = 1; i <= N; ++i) { read(P[i].x); read(P[i].y); } for (int i = 1; i <= N; ++i) { for (int j = i + 1; j <= N; ++j) { a[i][j] |= (1 << i - 1) | (1 << j - 1); for (int k = 1; k <= N; ++k) { if (k == i || k == j) continue; if ((P[k] - P[i]) * (P[j] - P[i]) == 0 && dot(P[k] - P[i], P[j] - P[i]) >= 0 && (P[k] - P[i]).norm() < (P[j] - P[i]).norm()) { a[i][j] |= (1 << k - 1); } } a[j][i] = a[i][j]; } } for (int i = 0; i < N; ++i) pos[1 << i] = i + 1; for (int i = 1; i <= N; ++i) { f[i][1 << i - 1] = 1; } for (int S = 1; S < (1 << N); ++S) { for (int T = S; T; T -= lowbit(T)) { int h = pos[lowbit(T)]; if (!f[h][S]) continue; for (int j = 1; j <= N; ++j) { if ((S & (1 << j - 1)) == 0) { if ((a[h][j] & (S | (1 << j - 1))) == a[h][j]) update(f[j][S ^ (1 << j - 1)], f[h][S]); } } } } int ans = 0; for (int S = 1; S < (1 << N); ++S) { cnt[S] = cnt[S - lowbit(S)] + 1; if (cnt[S] >= 4) { for (int i = 1; i <= N; ++i) update(ans, f[i][S]); } } out(ans); enter; } int main() { #ifdef ivorysi freopen("f1.in", "r", stdin); #endif Solve(); return 0; }