因为 i < j i < j i<j,所以所有的 [ i , j ] [i, j] [i,j]区间中都至少包含两个相邻元素,所以只要求出所有相邻元素中较大值的最小值即可。
int n;
int a[N];
void solve() {
cin >> n;
int min_v = 1e9 + 1;
for (int i = 1; i <= n; i ++) {
cin >> a[i];
}
for (int i = 1; i <= n - 1; i ++) {
min_v = min(min_v, max(a[i], a[i + 1]));
}
cout << min_v - 1 << '\n';
}
观察结论,发现样例 4 4 4的答案是 2 25 = 33554432 2^{25} = 33554432 225=33554432,猜测所有答案都是 2 2 2的次方。
以样例 3 3 3为例:
5432 10 5432 10
57: 1110 01 37: 1001 01
0100 00 0011 00
0100 01 0011 01
0100 10 0011 10
0100 11 0011 11
发现 x x x和 y y y的最长公共后缀对应的位可以从 0 0 0开始连续地填,从 00 00 00填到 11 11 11就走完了这两位可以提供的所有连续数值。如果从 000 000 000填到 111 111 111的话,因为更高位 x x x和 y y y的值不同,所以异或出来的值不是连续的。
再看 5432 5432 5432位,我们要保证 x x x和 y y y都不能填 0000 0000 0000,因为 0000 0000 0000会和后面两位 00 00 00组成 0 0 0,但是题目要求是从 1 1 1开始。假设 x x x填 0001 0001 0001,如果 y y y必须填 0000 0000 0000才能保证前缀异或相同,那么我们可以把 x x x改填 0011 0011 0011,因为异或的性质,原本第 3 3 3位取的是 x x x的第三位,现在我们改成 1 1 1,就是取 x x x的第三位取反,那么 y y y的第三位就也必须取反,那么 y y y就得填 0010 0010 0010。这样,我们总可以不用选 0000 0000 0000去填。
int x, y;
void solve() {
cin >> x >> y;
int i;
for (i = 0; i <= 30; i ++) {
if ((x >> i & 1) != (y >> i & 1)) {
cout << (1 << i) << '\n';
return;
}
}
cout << (1 << i) << '\n';
}
吐槽:忘了删刚开始猜的判断 − 1 -1 −1的情况,导致赛时一直 W A 8 WA \ 8 WA 8。
更新:刚开始猜的是对的,在判断 f l a g = = 1 flag == 1 flag==1时应该这样写:
flag > 1 && fabs(flag - 1) < 1e-6
设 x x x的总和为 s s s。
因为 k i ∗ x i > s k_i * x_i > s ki∗xi>s,所以 x i > = s / k i + 1 x_i >= s / k_i + 1 xi>=s/ki+1,然后我们要保证所有的 s / k i + 1 s / k_i + 1 s/ki+1加起来小于等于 s s s。因为这样我们可以在每个 s / k i + 1 s / k_i + 1 s/ki+1上加若干值使得他们的总和等于 s s s,且仍然满足 k i ∗ x i > s k_i * x_i > s ki∗xi>s。
那么我们可以二分查找这个 s s s,找不到就输出 − 1 -1 −1。
int n;
int k[55];
int a[55];
bool check(int x) {
int sum = x ;
for (int i = 1; i <= n; i ++) {
sum -= x / k[i];
}
return sum >= n;
}
void solve() {
cin >> n;
for (int i = 1; i <= n; i ++) {
cin >> k[i];
}
// double flag = 0;
// for (int i = 1; i <= n; i ++) {
// flag += (double)1 / (double)k[i];
// }
// if (flag > 1 || fabs(flag - 1) < 1e-6) {
// cout << -1 << '\n';
// return;
// }
int l = n - 1, r = n * (int)1e9 + 1;
while (l < r) {
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
int s = l;
if (s == n - 1 || s == n * (int)1e9 + 1) {
cout << -1 << '\n';
return;
}
// cout << l << '\n';
int sum = 0;
for (int i = 1; i <= n; i ++) {
a[i] = s / k[i] + 1;
sum += a[i];
}
int cnt = l - sum;
a[1] += cnt;
for (int i = 1; i <= n; i ++) {
cout << a[i] << ' ';
}
cout << '\n';
// sum = 0;
// for (int i = 1; i <= n; i ++) {
// sum += a[i];
// }
// for (int i = 1; i <= n; i ++) {
// cout << a[i] * k[i] - sum << ' ';
// }
// cout << '\n';
}
因篇幅问题不能全部显示,请点此查看更多更全内容