QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#773167 | #7932. AND-OR closure | ucup-team2172 | WA | 1ms | 7828kb | C++14 | 2.6kb | 2024-11-23 02:40:47 | 2024-11-23 02:40:47 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
const int n = 40;
const long long FULL = (1ll << n) - 1;
const int maxn = 45;
const int maxm = 2e5 + 5;
int m;
long long a[maxm];
int clk = 0, top = 0, tot = 0;
int low[maxn], dfn[maxn], stk[maxn], ins[maxn], col[maxn];
vector<int> g[maxn];
inline void tarjan(int u) {
low[u] = dfn[u] = clk++;
ins[stk[++top] = u] = true;
for (auto v: g[u]) {
if (!~dfn[v]) tarjan(v), low[u] = min(low[u], low[v]);
else if (ins[v]) low[u] = min(low[u], dfn[v]);
}
if (low[u] == dfn[u]) {
for (int v = stk[top]; ; v = stk[--top]) {
col[v] = tot;
ins[v] = false;
if (v == u) break;
}
++tot;
}
}
int ed[maxn][maxn];
long long to[maxn], from[maxn];
long long h[1 << n / 2];
long long OCC = 0, AND;
inline void scc() {
memset(dfn, -1, sizeof(dfn));
for (int x = 0; x < n; ++x) if ((OCC >> x & 1) && !~dfn[x]) tarjan(x);
for (int x = 0; x < n; ++x) for (auto y: g[x]) if (col[x] != col[y]) ed[col[x]][col[y]] = 1, printf("edge %d %d\n", col[x], col[y]);
for (int k = 0; k < tot; ++k) for (int i = 0; i < tot; ++i) for (int j = 0; j < tot; ++j)
if (ed[i][k] && ed[k][j]) ed[i][j] = 1;
for (int i = 0; i < tot; ++i) for (int j = 0; j < tot; ++j) if (ed[i][j])
to[tot - i - 1] |= 1ll << (tot - j - 1), from[tot - j - 1] |= 1ll << (tot - i - 1);
}
int f[1 << n / 2], r[1 << n / 2];
int main(){
scanf("%d", &m);
OCC = 0;
AND = FULL;
for (int i = 0; i < m; ++i) scanf("%lld", a + i), OCC |= a[i], AND &= a[i];
for (int x = 0; x < n; ++x) if (OCC >> x & 1){
long long sum = FULL;
for (int i = 0; i < m; ++i) if (a[i] >> x & 1) sum &= a[i];
for (int y = 0; y < n; ++y) if (sum >> y & 1) g[x].push_back(y);
}
scc();
const int half = tot / 2;
const int left = (1 << half) - 1;
for (int S = 0; S < (1 << half); ++S) {
f[S] = 1;
for (int i = 0; i < half; ++i) if (S >> i & 1) f[S] &= ((to[i] & left & S) == (to[i] & left));
}
for (int S = 0; S < (1 << tot - half); ++S) {
r[S] = 1;
for (int i = 0; i < tot - half; ++i) if (S >> i & 1) r[S] &= (((to[i + half] >> half) & S) == (to[i + half] >> half));
}
for (int i = 0; i < half; ++i) for (int S = 0; S < (1 << half); ++S) if (S >> i & 1) f[S] += f[S ^ (1 << i)];
for (int S = 1; S < (1 << tot - half); ++S) for (int i = 0; i < tot - half; ++i)
if (S >> i & 1) h[S] = h[S ^ (1 << i)] | from[i + half];
long long ans = 0;
for (int S = 0; S < (1 << tot - half); ++S) if (r[S]){
long long ban = h[(1 << tot - half) - 1 - S] & left;
ans += f[(1 << half) - 1 - ban];
}
if (AND) --ans;
printf("%lld\n", ans);
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 0
Wrong Answer
time: 1ms
memory: 7828kb
input:
4 0 1 3 5
output:
edge 1 0 edge 2 0 5
result:
wrong output format Expected integer, but "edge" found