牛客小白月赛57

简介: 笔记

A 最大面积


题目

30.png


输入

31.png


输出

32.png



示例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 种树


题目

33.png


输入

34.png


输出

35.png


示例1


输入


7

0111110


输出


2


思路

注意题目说的:“一个地方可以种多棵树。”


左侧有 0 可以由右侧某个1 向左种树


右侧有 0可以由左侧某个 1 向右种树


即:字符串首尾两位 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 奇怪的电梯


题目


36.png

输入


37.png

输出

38.png


示例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 , b > a , a = = b ) (a>b,b>a,a==b)(a>b,b>a,a==b)

39.png

a==b:yes


b>a:(如上图所示)


这里需要继续分情况,在此只考虑yes的情况

b−a>k:a − > b

n−b>k:a − > n − > b

a−1>k:a − > 1 − > b

n−a>k&&b−1>k:a − > n − > 1 − > b

a > b a>ba>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


题目

40.png


输入

41.png


输出

42.png


示例1


输入


3

1 2 2


输出


2


思路

这题一眼n 2

2

暴力结束。。。T的飞起


考虑题目范围n≤1e6,并且每个数的大小a[i]≤1e6。


我们可以从原先找每两个数的gcd 取最大,转为找出每个数的约数,这样最大存在的约数并且个数大于等于2 ,那么就是答案。


我们考虑 nlogn的算法来实现,又已知 nlogn 能打出 1 ~ n 范围内的所有约数。


大概思路就是枚举每个数 i 的倍数,那么 i ∗ j 的约数就有 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 一道难题


题目


43.png

输入


44.png

输出

45.png


示例1


输入


2001


输出


3


说明

1 − 2001 1−20011−2001 中,满足条件的数有:111 , 1110 , 1111 111,1110,1111111,1110,1111。


思路

题目输入的是十进制的数,但是题目要求的是由 0 00 或 1 11 组成的。


所以可以发现,满足题目的条件的十进制数,实际上与相同位数的二进制数对应。


那么可以求出不超过 n nn 的最大的二进制形式,应该对应的十进制数值。


对于每一个数,都当成一个二进制数看。然后在暴力枚举,判断符合条件即可。


代码

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;
}


F 序列操作


相关文章
|
6月前
|
人工智能 BI
牛客小白月赛66
牛客小白月赛66
38 0