C. Bitwise Balancing (C)
先求出 \(b - c\) 的值,再考慮 \(a\) 的每個二進位制位取0或1對答案的影響。vp的時候不知道為什麼錯了很多次。
void solve() {
ll b, c, d;
scanf("%lld%lld%lld", &b, &c, &d);
if(b - c > d) {
printf("-1\n");
return;
}
ll x = d - (b - c), cst = 0;
for(int r = 0; r < 61; r++) {
ll y = 1ll << r;
if((y & b) == 0 && (y & c)) cst |= y;
}
x -= cst;
if(x < 0) {
printf("-1\n");
return;
}
ll add = 0, sub = 0;
for(int r = 0; r <= 61; r++) {
ll y = 1ll << r;
if((y & b) == 0 && (y & c) == 0) add |= y;
else if((y & b) && (y & c)) add |= y, sub |= y;
}
if((x & add) == x && (x ^ sub) <= (1ll << 61)) printf("%lld\n", x ^ sub);
else printf("-1\n");
}
D. Connect the Dots (D)
注意到 \(d \leq 10\),用10個並查集儲存連邊操作為 \(d_i\) 時的連通情況,同時維護每個並查集的右端點,每次從當前並查集最右側開始遍歷,可避免 \(d_i\) 相同時、對同一個點多次操作導致TLE. 最後合併每層的資訊即可。
const int N = 2e5 + 10;
int f[12][N], r[12][N];
int find(int id, int i) {
if(f[id][i] == i) return i;
return f[id][i] = find(id, f[id][i]);
}
void merge(int id, int x, int y) {
int fx = find(id, x), fy = find(id, y);
f[id][fy] = fx;
r[id][fx] = max(r[id][fx], r[id][fy]);
}
void solve() {
int n, m;
scanf("%d%d", &n, &m);
for(int i = 0; i <= 10; i++) {
for(int j = 1; j <= n; j++) {
r[i][j] = f[i][j] = j;
}
}
while(m--) {
int a, d, k;
scanf("%d%d%d", &a, &d, &k);
if(find(d, a) != find(d, a + d * k)) {
for(int i = a + d;;) {
merge(d, a, i);
if(find(d, a) == find(d, a + d * k)) break;
int x = r[d][find(d, i)];
i = x + d;
}
}
}
for(int i = 1; i <= 10; i++) {
for(int j = 1; j <= n; j++) {
int fa = find(i, j);
if(fa != j) merge(0, j, fa);
}
}
int cnt = 0;
for(int i = 1; i <= n; i++) {
if(f[0][i] == i) cnt++;
}
printf("%d\n", cnt);
}
E. Expected Power (E)
\(f(s)^2 = \sum\limits_{i = 0} ^ 9 \sum\limits_{j = 0} ^ 9 b_ib_j \times 2^{i + j}\),對每個二進位制位,\(b_i\) 和 \(b_j\) 最多有4種不同的組合,維護每位每種情況的機率即可求得期望。
void solve() {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
ll b = inv(10000);
memset(dp, 0, sizeof(dp));
for(int i = 1; i <= n; i++) {
int p;
scanf("%d", &p);
p1[i] = p * b % mo;
p0[i] = (1 - p1[i] + mo) % mo;
}
for(int i = 0; i < 10; i++) {
for(int j = 0; j < 10; j++) {
dp[i][j][0][0] = 1;
}
}
for(int i = 1; i <= n; i++) {
for(int j = 0; j < 10; j++) {
for(int k = 0; k < 10; k++) {
int t1 = (a[i] >> j) & 1, t2 = (a[i] >> k) & 1;
ll tmp[2][2];
for(int p : {0, 1}) {
for(int q : {0, 1}) {
tmp[p][q] = dp[j][k][p][q] * p0[i] % mo + dp[j][k][p ^ t1][q ^ t2] * p1[i] % mo;
if(tmp[p][q] >= mo) tmp[p][q] -= mo;
}
}
for(int p : {0, 1}) {
for(int q : {0, 1}) {
dp[j][k][p][q] = tmp[p][q];
}
}
}
}
}
ll ans = 0;
for(int i = 0; i < 10; i++) {
for(int j = 0; j < 10; j++) {
ans += dp[i][j][1][1] * (1 << i + j) % mo;
if(ans >= mo) ans -= mo;
}
}
printf("%lld\n", ans);
}
F還沒補