#include <bits/stdc++.h>
using namespace std;
#define PB push_back
typedef vector<int> VI;
VI a;
int main() {
int t;
scanf("%d", &t);
while (t -- ) {
a.clear();
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i ++ ) {
int tmp;
scanf("%d", &tmp);
a.PB(tmp);
}
bool ok = 1;
int num1, num2;
for (int i = 0; i < n; i ++ )
if (a[i] != a[n - i - 1]) {
ok = 0;
num1 = a[i];
num2 = a[n - i - 1];
break;
}
if (ok) {
printf("YES\n");
continue;
}
ok = 1;
for (int i = 0, j = n - 1; i < j; ) {
if (a[i] == a[j]) {
i ++, j --;
} else if (a[i] == num1) {
while (a[i] != a[j] && a[i] == num1 && i < j) i ++;
if (a[i] != a[j]) {
ok = 0;
break;
}
} else if (a[j] == num1) {
while (a[i] != a[j] && a[j] == num1 && i < j) j --;
if (a[i] != a[j]) {
ok = 0;
break;
}
} else {
ok = 0;
break;
}
}
if (ok) {
printf("YES\n");
continue;
}
ok = 1;
for (int i = 0, j = n - 1; i < j; ) {
if (a[i] == a[j]) {
i ++, j --;
} else if (a[i] == num2) {
while (a[i] != a[j] && a[i] == num2 && i < j) i ++;
if (a[i] != a[j]) {
ok = 0;
break;
}
} else if (a[j] == num2) {
while (a[i] != a[j] && a[j] == num2 && i < j) j --;
if (a[i] != a[j]) {
ok = 0;
break;
}
} else {
ok = 0;
break;
}
}
if (ok) printf("YES\n");
else printf("NO\n");
}
return 0;
}
看数据量就是
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn),想到二分。二分答案,然后对于
m
i
d
mid
mid 来说,a[i] >= mid - i && b[i] >= i - 1
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int a[N], b[N];
int n;
bool check(int mid) {
int cnt = mid;
int up = mid - 1, down = 0;
for (int i = 1; i <= n; i ++ ) {
if (a[i] >= up && b[i] >= down) {
up --, down ++;
cnt --;
if (cnt == 0) break;
}
}
bool ok = 1;
if (cnt == 0) ok = 1;
else ok = 0;
return ok;
}
int main() {
int t;
scanf("%d", &t);
while (t -- ) {
scanf("%d", &n);
for (int i = 1; i <= n; i ++ )
scanf("%d%d", a + i, b + i);
int l = 1, r = n;
while (l < r) {
int mid = (l + r + 1) / 2;
if (check(mid)) l = mid;
else r = mid - 1;
}
cout << l << endl;
}
return 0;
}
首先对于任意一个数
x
x
x,他的和是
x
∗
(
x
+
1
)
2
\displaystyle \frac{x * (x + 1)}{2}
2x∗(x+1)
对于
a
1
,
a
2
,
a
3
,
.
.
.
,
a
n
a_1, a_2, a_3, ..., a_n
a1,a2,a3,...,an 来说,他们的和
s
u
m
=
sum =
sum=
a
1
∗
(
a
1
+
1
)
2
\displaystyle \frac{a_1 * (a_1 + 1)}{2}
2a1∗(a1+1)
+
+
+
a
2
∗
(
a
2
+
1
)
2
\displaystyle \frac{a_2 * (a_2 + 1)}{2}
2a2∗(a2+1)
+
.
.
.
+
+ ...+
+...+
a
n
∗
(
a
n
+
1
)
2
\displaystyle \frac{a_n * (a_n + 1)}{2}
2an∗(an+1),他们的和可以变化的最小间距是
g
c
d
(
a
1
,
a
2
,
a
3
,
.
.
.
,
a
n
)
gcd(a_1, a_2, a_3, ..., a_n)
gcd(a1,a2,a3,...,an) (显然,不会证明)
那么我要使
s
u
m
=
0
sum = 0
sum=0,条件就是
s
u
m
∣
g
c
d
sum | gcd
sum∣gcd
奇数很好处理,奇数和偶数凑一起,
g
c
d
=
1
gcd = 1
gcd=1,不用管奇数了
偶数的就是二进制的最小位
举个例子
x
x
x 的最小二进制位在
i
i
i 位上,
x
∗
(
x
+
1
)
2
\displaystyle \frac{x * (x + 1)}{2}
2x∗(x+1) 肯定不能整除
2
i
2 ^ i
2i,如果是偶数个
x
x
x 就可以,如果最小二进制位为
i
i
i 个数为
n
u
m
num
num 个,那么他们组成的奇数方案数为
2
n
u
m
−
1
2^{num - 1}
2num−1 个,他们组成的偶数方案数为
2
n
u
m
−
1
2^{num - 1}
2num−1 个,我们不用考虑最小二进制在
i
+
1
i + 1
i+1 上的
x
1
x_1
x1,因为他们的和
x
1
∗
(
x
1
+
1
)
2
\displaystyle \frac{x_1 * (x_1 + 1)}{2}
2x1∗(x1+1) 肯定可以被
2
i
2 ^ i
2i 整除
我们先列出最多多少种方案,
2
n
−
1
2 ^ n - 1
2n−1 种,减去不合适的方案数,二进制位为
i
i
i 个数为
n
u
m
num
num 个,他们组成的奇数方案数为
2
n
u
m
−
1
2^{num - 1}
2num−1 个,同时他们和任何二进制位比
i
i
i 高的任何数都不能成方案
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
int num[40], base[N];
int main() {
base[0] = 1;
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i ++ )
base[i] = (base[i - 1] * 2) % mod;
for (int i = 1; i <= n; i ++ ) {
int tmp;
scanf("%d", &tmp);
int cnt = 0;
while (tmp % 2 == 0) {
tmp /= 2;
cnt ++;
}
num[cnt] ++;
}
int sum = 0;
LL ans = base[n] - 1;
for (int i = 32; i; i -- ) {
if (!num[i]) continue;
sum += num[i];
ans = (ans - base[sum - 1] + mod) % mod;
}
cout << ans << endl;
return 0;
}