BZOJ2560串珠子
阿新 • • 發佈:2019-03-10
continue def har tchar turn else digi ret 等於
/* 很清新的一道題(相比上一道題) g[S]表示該 S集合中胡亂連的所有方案數, f[S] 表示S集合的答案 那麽F[S] 等於G[S]減去不合法的部分方案 不合法的方案就枚舉合法的部分就好了 g[S]求法可以由選擇一個點和其他沒被選擇的之間連邊的 */ #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<queue> #include<cmath> #define ll long long #define M 16 #define mmp make_pair using namespace std; const int mod = 1000000007; void add(int &x, int y) { x += y; x -= x >= mod ? mod : 0; x += x < 0 ? mod : 0; } int read() { int nm = 0, f = 1; char c = getchar(); for(; !isdigit(c); c = getchar()) if(c == '-') f = -1; for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0'; return nm * f; } int poww(int a, int b) { int ans = 1, tmp = a; for(; b; b >>= 1, tmp = 1ll * tmp * tmp % mod) if(b & 1) ans = 1ll * ans * tmp % mod; return ans; } int f[1 << M], g[1 << M], a[M][M], n; int main() { n = read(); for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { a[i][j] = read(); } } f[0] = g[0] = 1; for(int i = 1; i < (1 << n); i++) { int x = -1, ans = 1; for(int j = 0; j < n; j++) { if((i & (1 << j)) == 0) continue; if(x == -1) x = j; else { ans = 1ll * ans * (a[x][j] + 1) % mod; } } g[i] = 1ll * g[i ^ (1 << x)] * ans % mod; } for(int i = 1; i < (1 << n); i++) { f[i] = g[i]; int k = i ^ (i & -i); for(int j = k; j; j = (j - 1) & k) { add(f[i], -1ll * g[j] * f[i ^ j] % mod); } } cout << f[(1 << n) - 1] << "\n"; return 0; }
BZOJ2560串珠子