voidread(__int128 &x){ // read a __int128 variable char c; bool f = 0; while(((c = getchar()) < '0' || c > '9') && c != '-'); if(c == '-'){f = 1; c = getchar();} x = c - '0'; while((c = getchar()) >= '0' && c <= '9')x = x * 10 + c - '0'; if(f) x = -x; } voidwrite(__int128 x){ // print a __int128 variable if(x < 0){putchar('-'); x = -x;} if(x > 9)write(x / 10); putchar(x % 10 + '0'); }
int dataID, T, n, m, k, b[100005]; __int128 a[100005], ans; structTrie { int tot, trie[12000005][2]; __int128 mn[12000005]; longlong sum[12000005];
Trie() {memset(mn, 0x3f, sizeof(mn));} voidclear(){ for (int i = 0; i <= tot; i++) trie[i][0] = trie[i][1] = 0, mn[i] = (__int128)1 << 121, sum[i] = 0; tot = 0; return ; } voidinsert(__int128 x, int val){ int now = 0; for (int i = k - 1; i >= 0; i--) { int id = x >> i & 1; if (!trie[now][id]) trie[now][id] = ++tot; now = trie[now][id]; mn[now] = min(mn[now], x), sum[now] += val; } return ; } voiddfs(int now, int h, int m, __int128 mnS, __int128 val, __int128 x){ if (h == -1) {ans = max(ans, val ^ x); return ;} __int128 bit = (__int128)1 << h, rest = bit - 1; if (!now && h != k - 1) {ans = max(ans, mnS + (x | bit | rest)); return ;} int flag = 0; if (sum[trie[now][1]] <= m && (x | bit | rest) + min(mnS, mn[trie[now][1]]) >= ((val ^ x) | bit)) { dfs(trie[now][0], h - 1, m - sum[trie[now][1]], min(mnS, mn[trie[now][1]]), val, x | bit); flag = 1; } if (sum[trie[now][0]] <= m && (x | rest) + min(mnS, mn[trie[now][0]]) >= ((val ^ x) | bit)) { dfs(trie[now][1], h - 1, m - sum[trie[now][0]], min(mnS, mn[trie[now][0]]), val | bit, x); flag = 1; } if (!flag) { dfs(trie[now][0], h - 1, m, mnS, val, x); dfs(trie[now][1], h - 1, m, mnS, val | bit, x | bit); } return ; } } tr;
intmain(){ // freopen("xor.in", "r", stdin); // freopen("xor.out", "w", stdout); scanf("%d%d", &dataID, &T); while (T--) { scanf("%d%d%d", &n, &m, &k); tr.clear(); for (int i = 1; i <= n; i++) read(a[i]); longlong sum = 0; __int128 mnS = (__int128)1 << 121; for (int i = 1; i <= n; i++) scanf("%d", &b[i]), tr.insert(a[i], b[i]), sum += b[i]; ans = 0; tr.dfs(0, k - 1, m, mnS, 0, 0); if (sum <= m) { __int128 res = (__int128)1 << 121; for (int i = 1; i <= n; i++) res = min(res, a[i]); ans = max(ans, res + ((__int128)1 << k) - 1); } write(ans); puts(""); } return0; }
Day1T3 虫洞 wormhole
还不会。
Day2T1 迷宫守卫 maze
简单题,设 fi,j 表示只考虑子树 i,要使排列第一位是 j 的最小代价。设 Si 表示 i 子树中数的集合,则有状态转移方程:
scanf("%d%d%d", &n, &m, &k); U = (1 << n) - 1; for (int i = 1; i <= m; i++) { int u, v; scanf("%d%d", &u, &v); u--, v--; pre[1 << v] |= 1 << u; } for (int S = 1; S < 1 << n; S++) { int lowbit = S & -S; pre[S] = (pre[S ^ lowbit] | pre[lowbit]) & (U ^ S); } for (int S = 1; S < 1 << n; S++) toposort(S);
g[0][0] = 1; for (int S = 1; S < 1 << n; S++) for (int i = 1; i <= n; i++) for (int T = S; T; T = (T - 1) & S) if ((T & -T) == (S & -S) && !(pre[T] & (S ^ T)) && !(pre[S ^ T] & T)) g[S][i] = (g[S][i] + (longlong)g[S ^ T][i - 1] * ts[T]) % mod; for (int S = 1; S < 1 << n; S++) for (int i = 0; i <= n; i++) for (int j = 0, pw = 1; j <= n; j++, pw = (longlong)pw * i % mod) if (j % 2) gv[S][i] = (gv[S][i] + (longlong)g[S][j] * pw) % mod; else gv[S][i] = (gv[S][i] + mod - (longlong)g[S][j] * pw % mod) % mod; for (int i = 0; i <= n; i++) dp[0][i] = 1; for (int S = 1; S < 1 << n; S++) for (int T = S; T; T = (T - 1) & S) if (!(pre[T] & S)) for (int i = 0; i <= n; i++) dp[S][i] = (dp[S][i] + (longlong)dp[S ^ T][i] * gv[T][i]) % mod; vector<int> poly, tmp; poly.push_back(0); tmp.push_back(1); for (int i = 0; i <= n; i++) { vector<int> tmpm; tmpm.push_back(mod - i), tmpm.push_back(1); tmp = mul(tmp, tmpm); } for (int i = 0; i <= n; i++) { int c = dp[U][i]; for (int j = 0; j <= n; j++) if (j != i) c = (longlong)c * power((i - j + mod) % mod, mod - 2) % mod; poly = pls(poly, mul(div(tmp, i), c)); } poly.push_back(0);
for (int i = 0; i <= k + 1; i++) for (int j = 0; j <= i; j++) if (j == 0 || j == i) C[i][j] = 1; else C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod; fac[0] = 1; for (int i = 1; i <= n; i++) fac[i] = (longlong)fac[i - 1] * i % mod; int ans = 0; for (int i = 1; i <= k + 1; i++) ans = (ans + (longlong)poly[i] * fac[i] % mod * fac[k] % mod * C[k + 1][i]) % mod;
f[0][0] = 1; for (int i = 1; i <= n + 1; i++) for (int j = 0; j <= k; j++) { if (j == 0) {f[i][j] = 1; continue;} if (j == 1) {f[i][j] = (longlong)i * (k - j + 1) % mod; continue;} for (int o = 0; o <= i; o++) f[i][j] = (f[i][j] + f[o][j - 1]) % mod; f[i][j] = (longlong)f[i][j] * (k - j + 1) % mod; }
ans = (longlong)ans * power((longlong)fac[n] * f[n + 1][k] % mod, mod - 2) % mod; printf("%d\n", ans);