HNCU程序设计周赛(3)

admin 发布于 2024-11-16 1770 字 551 次阅读


A-打靶

首先已有的分数X已经大于最终的分数Y,则肯定是No的;

然后再看剩余的靶子与X的和是否大于等于Y即可;

#include<bits/stdc++.h>
#define ll long long

#define endl '\n'
using namespace std;

const int N = 1e6 + 5;

void solve()
{
    int n, m, x, y;
    cin >> n >> m >> x >> y;
    if (x > y) {
        cout << "No" << endl;
        return;
    }
    if (x + n - m >= y) cout << "Yes" << endl;
    else cout << "No" << endl;
}
signed main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--)
        solve();
    return 0;
}

B-国际裁判带师

每次模拟即可’

#include<bits/stdc++.h>
#define ll long long

using namespace std;

const int N = 1e6 + 5;


//check函数用来计算x有多少个0
int check(int x)
{
    if (x == 0) return 1;
    int cnt = 0;
    while (x) {
        if (x % 10 == 0) cnt++;
        x /= 10;
    }
    return cnt;
}
void solve()
{
    string s;
    cin >> s;
    int sum1 = 0, sum2 = 0, ans = 0; // sum1代表红方获得的分数,sum2代表蓝方获得的分数
// ans用于记录答案
    for (int i = 0; i < s.size(); i++) {
        if (s[i] == 'a') {
            sum1++;
            if (sum1 < 10) ans++; // 得分若是个位,那么必定有一位是0
            if (sum2 < 10) ans++;
            ans += check(sum1);
            ans += check(sum2);
        }
        else {
            sum2++;
            if (sum1 < 10) ans++;
            if (sum2 < 10) ans++;
            ans += check(sum1);
            ans += check(sum2);
        }
    }
    cout << ans << endl;
}
signed main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
//    int t;
//    cin >> t;
//    while (t--)
        solve();
    return 0;
}

#include <stdio.h>
#include <string.h>

int check(int x) {
    if (x == 0) return 1;

    int cnt = 0;
    while (x) {
        if (x % 10 == 0) cnt++;
        x /= 10;
    }
    return cnt;
}

int main() {
    char s[1000];
    scanf("%s", s);
    int sum1 = 0, sum2 = 0, ans = 0;
    int len = strlen(s);
    for (int i = 0; i < len; i++) {
        if (s[i] == 'a') {
            sum1++;
            if (sum1 < 10) ans++;
            if (sum2 < 10) ans++;
            ans += check(sum1);
            ans += check(sum2);
        } else {
            sum2++;
            if (sum1 < 10) ans++;
            if (sum2 < 10) ans++;
            ans += check(sum1);
            ans += check(sum2);
        }
    }
    printf("%d", ans);
    return 0;
}

C-上班

超级水的题

只需输出x加上y跟z的最小值即可

#include<bits/stdc++.h>
#define ll long long

#define endl '\n'
using namespace std;

const int N = 1e6 + 5;

void solve()
{
    int x, y, z;
    cin >> x >> y >> z;
    cout << x + min(y, z) << endl;
}
signed main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
//    int t;
//    cin >> t;
//    while (t--)
        solve();
    return 0;
}

D- X

我们知道正对角线横坐标的值跟纵坐标的值相等,副对角线横坐标与纵坐标的和为定值,

那么知道这个就简单了

#include<bits/stdc++.h>
#define ll long long

#define endl '\n'
using namespace std;

const int N = 1e6 + 5;

void solve()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            if (i == j || i + j == n + 1) cout << "*";
            else cout << " ";
        }
        cout << endl;
    }
}
signed main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
//    int t;
//    cin >> t;
//    while (t--)
        solve();
    return 0;
}

E-最大子段和

注意是非空序列,我们贪心的想,只要是某一段和是大于0的,那么加上这一段肯定会更优,

如果这一段小于0了,那么肯定是直接舍弃,基于这个思想遍历数组记录最大值即可。

#include<bits/stdc++.h> // 万能头文件
#define ll long long

#define endl '\n'
using namespace std;

const int N = 2e5 + 5, INF = 1e9;


int a[N];
void solve()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    ll ans = -INF, sum = 0;
    for (int i = 1; i <= n; i++) {
        sum += a[i];
        ans = max(ans, sum);  // 记录此过程的最大值
        if (sum < 0) sum = 0; // 这一段要是小于0了,那么直接舍弃
    }
    cout << ans << endl;
}
signed main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
//    int t;
//    cin >> t;
//    while (t--)
        solve();
    return 0;
}

F-天

注意只能选择向下或者向右移动
从左上角开始暴力走所有可能的路径,使用另一个数组记录可以走到的位置
假设现在在点(x,y)且这个点可以被走到,此时(x-1,y)已经被走到,则记录点(x,y)
时间复杂度O(n*m)

#include<bits/stdc++.h> // 万能头文件
#define ll long long

#define endl '\n'
using namespace std;

const int N = 2e5 + 5;
 
int st[105][105];    // st数组代表这一个地方是否可以走到 
char c[105][105]; 
void solve() { 
    int n, m; 
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> c[i][j];
        }
    }
    st[1][1] = 1; 
    for (int i = 1; i <= m; i++) 
        for (int j = 1; j <= n; j++) { 
            if (c[j][i] == '#') continue; 
            if (st[j - 1][i] || st[j][i - 1]) st[j][i] = 1; 
            // (j, i) 可以从 (j - 1, i), (j, i - 1)两个位置走到 
        } 
    if (st[n][m]) cout << "YES" << endl; 
    else cout << "NO" << endl;
} 
signed main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
//    int t;
//    cin >> t;
//    while (t--)
        solve();
    return 0;
}

G-取玻璃珠游戏

签到题(绝对!!!)

由于每次只能取一个玻璃珠,所以总和为奇数则seele赢

否则vollerei赢

#include<bits/stdc++.h>
#define ll long long

#define endl '\n'
using namespace std;

const int N = 2e5 + 5;


void solve()
{
    int n;
    cin >> n;
    int sum = 0;
    for (int i = 1; i <= n; i++) {
        int x;
        cin >> x;
        sum += x;
    }
    if (sum % 2) cout << "seele" << endl;
    else cout << "vollerei" << endl;
}
signed main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
//    int t;
//    cin >> t;
//    while (t--)
        solve();
    return 0;
}

H-远平面

考虑花费为0时最多能有几个点,很显然只有1个,(放原点)

花费为1时最多能有几个点,容易知道最多只能放四个点(1,0),(-1,0),(0,1),(0,-1);

则当花费为i时,最多能放y个点

i = 0, y = 1;

i = 1, y = 4;

i = 2, y = 9;

i = 3, y = 16;

........

i = n,y = (i + 1)* (i + 1);

所以应该知道了吧

#include<bits/stdc++.h>
#define ll long long

#define endl '\n'
using namespace std;

const int N = 2e5 + 5;


void solve()
{
    ll n; // 注意n的范围
    cin >> n;
    cout << (ll)sqrt(n - 1) << endl;
}
signed main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--)
        solve();
    return 0;
}

I,J-樱公馆(困难版本)

数据范围1<=n<=10000
暴力模拟时间复杂度O(n*k)的办法可以通过

#include<bits/stdc++.h>
#define ll long long

#define endl '\n'
using namespace std;

const int N = 2e5 + 5;
int q[10005], r[10005], l[10005], n, k; 
// q数组代表最开始球的数值,r代表该球右边的球是哪个球,l代表该球左边的球是哪个球 
void solve() { 
    
    cin >> n >> k;
    for (int i = 1; i <= n; i++){    
        cin >> q[i];
        r[i] = i + 1; 
        l[i] = i - 1; 
    } 
    r[n] = 1, l[1] = n; 
    int lse = 0, sum = 0;                    // lse代表进行到了第几步,sum代表移除球的数量 
    for (int i = 1; i <= n; i = r[i]){      // i代表此时a1的位置 
        if (lse == k){                       // lse == k,移除该球    
            r[l[i]] = r[i], l[r[i]] = l[i]; // 更新一下左右两球的l和r 
            cout << q[i] << " ";
            lse = 0; 
            sum++; 
        } 
        else lse++; 
        if (sum == n) break;                // 球已经全部移除 
    } 
} 
signed main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
//    int t;
//    cin >> t;
//    while (t--)
        solve();
    return 0;
}
最后更新于 2024-11-18