A 最大面积
题目
输入
输出
示例1
输入
2 2 3 2
输出
4
代码
void solve() {
int a, b, c, d; cin >> a >> b >> c >> d;
cout << min(a, c) * min(b, d) << endl;
}
B 种树
题目
输入
输出
示例1
输入
7
0111110
输出
2
思路
注意题目说的:“一个地方可以种多棵树。”
左侧有 0 0 0 可以由右侧某个 1 1 1 向左种树
右侧有 0 0 0 可以由左侧某个 1 1 1 向右种树
即:字符串首尾两位 0 0 0 的个数,决定了种的次数。
代码
void solve() {
int n; cin >> n;
string s; cin >> s;
int res = 0;
if (s[0] == '0') res++;
if (s.back() == '0') res++;
cout << res << endl;
}
C 奇怪的电梯
题目
输入
输出
示例1
输入
5
10 3 2 7
10 7 1 4
10 4 2 9
10 11 1 10
9 3 7 2
输出
YES
NO
YES
NO
YES
思路
事先声明:代码很丑,但思路非常简单!!!
题目问能否从 ( a − > b ) (a -> b) (a−>b),那很容易第一想法就是分情况 ( a > b , b > a , a = = b ) (a>b,b>a,a==b) (a>b,b>a,a==b)
-
a = = b a==b a==b:yes
-
b > a b>a b>a:(如上图所示)
- 这里需要继续分情况,在此只考虑
yes
的情况 -
- b − a > k b-a>k b−a>k: a − > b a->b a−>b
-
- n − b > k n-b>k n−b>k: a − > n − > b a->n->b a−>n−>b
-
- a − 1 > k a-1>k a−1>k: a − > 1 − > b a->1->b a−>1−>b
-
- n − a > k & & b − 1 > k n-a>k \&\& b - 1 > k n−a>k&&b−1>k: a − > n − > 1 − > b a->n->1->b a−>n−>1−>b
- 这里需要继续分情况,在此只考虑
-
a > b a>b a>b:同上思路
以上情况已经列明,具体的逻辑也应该非常清晰了,不在叙述每一步之间的大小关系了(自己想。
代码
void solve() {
int n, k, a, b; cin >> n >> k >> a >> b;
if (a == b) { puts("YES"); return ; }
if (a > b) {
if (n - a > k || a - b > k || b - 1 > k) { puts("YES"); return ; }
else if (a - 1 > k && n - b > k) { puts("YES"); return ; }
else { puts("NO"); return ; }
} else {
if (a - 1 > k || b - a > k || n - b > k) { puts("YES"); return ; }
else if (n - a > k && b - 1 > k) { puts("YES"); return ; }
else { puts("NO"); return ; }
}
}
D 最大gcd
题目
输入
输出
示例1
输入
3
1 2 2
输出
2
思路
这题一眼
n
2
n^2
n2暴力结束。。。T的飞起
考虑题目范围 n ≤ 1 e 6 n\leq1e6 n≤1e6,并且每个数的大小 a [ i ] ≤ 1 e 6 a[i]\leq1e6 a[i]≤1e6。
我们可以从原先找每两个数的 g c d gcd gcd 取最大,转为找出每个数的约数,这样最大存在的约数并且个数大于等于 2 2 2,那么就是答案。
我们考虑 n l o g n nlogn nlogn的算法来实现,又已知 n l o g n nlogn nlogn 能打出 1 1 1 ~ n n n 范围内的所有约数。
大概思路就是枚举每个数 i i i 的倍数,那么 i ∗ j i*j i∗j 的约数就有 i i i。和线性筛的思路有点相似,代码大概长这样:
// 求 1 ~ n 的约数
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n / i; j++)
a[i * j].push_back(i);
不过这题还需要有一个特判(由于我的实现方式导致的),需要对重复的数也计入答案的贡献。即代码中的:if (a[x] == 2) res = max(res, x);
因为if (a[i * j]) c[i]++;
,这行代码未考虑重数的情况。
代码
int a[N], c[N];
void solve() {
int n; scanf("%d", &n);
int res = -1;
for (int i = 1; i <= n; i++) { int x; cin >> x; a[x]++; if (a[x] == 2) res = max(res, x); }
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N / i; j++)
if (a[i * j]) c[i]++;
for (int i = 1; i < N; i++) if (c[i] >= 2) res = max(res, i);
cout << res << endl;
}
E 一道难题
题目
输入
输出
示例1
输入
2001
输出
3
说明
1 − 2001 1−2001 1−2001 中,满足条件的数有: 111 , 1110 , 1111 111,1110,1111 111,1110,1111。
思路
题目输入的是十进制的数,但是题目要求的是由 0 0 0 或 1 1 1 组成的。
所以可以发现,满足题目的条件的十进制数,实际上与相同位数的二进制数对应。
那么可以求出不超过 n n n 的最大的二进制形式,应该对应的十进制数值。
对于每一个数,都当成一个二进制数看。然后在暴力枚举,判断符合条件即可。
代码
void solve() {
string s; cin >> s;
int n = 0;
bool o = false;
for (int i = 0; i < s.sz; i++) {
if (o) { n += (1ll << (s.sz - i - 1)); continue; }
if (s[i] > '1') n += (1ll << (s.sz - i - 1)), o = true;
if (s[i] == '1') n += (1ll << (s.sz - i - 1));
}
auto check = [=](int x){
int cnt = 0;
while (x) {
if (x & 1) cnt++;
else cnt = 0;
if (cnt == 3) return true;
x >>= 1;
}
return false;
};
int res = 0;
for (int i = 1; i <= n; i++) {
if (check(i)) res++;
}
cout << res << endl;
}