2021 年第十三届四川省 ACM-ICPC 大学生程序设计竞赛



反思:这场比赛是在21/10/16队内赛下午打的,总的来说还是没状态,全靠队友了,自己题也看不懂,k题还没做完,队友就ac了两道题,雀氏是该多打打cf了
直接copy我的补题报告了,毕竟要给老师看的会写的更详细

A-Chuanpiao

这句话让我们猜了半天,实在想不出来跟题干有啥关系,后来直接忽略了,发现ac了(其实是个废话)

题意:就是给出数,让求出两组(1,6)有多少组合能加出这个数,打个表就行了

//  打表就行   0 1 1 2  2   3   3  3  2  2  1   1  


# include <iostream>

using namespace std;

int main(){
    int t,k;
    cin >> t;
    while (t --){
        cin >> k;
        
        if (k >= 1 &&k <= 7) printf("%d\n",k/2);
        
        else if (k == 8) printf("3\n");
        
        else if (k >=9 && k <= 10) printf("2\n");
        
        else if (k >= 11 && k <= 12) printf("1\n");
        
        else printf("0\n");
    }
    return 0;
}

K-skip Permutation

题意:一开始想错存个数组,用过了就归零,但想想还是太麻烦了,仔细想想这不就是个等差数列

题解:从1到n写出公差为k的等差数列,比如k=3,那么就是1,4,7...... 我们就在1~4这个k、区间for循环写出公差为k且小于等于n的等差数列就行,注意末尾无空格

# include <iostream>

using namespace std;

int a[1000];

int main(){
    int n , k;
    cin >> n >> k;
    int cnt = 0;
    
//     for (int i = 1; i <= n; i ++)
//         a[i] = i;
    
    // 等差数列
    for (int i = 1; i <= k; i ++){
        for (int j = 0; j * k + i <= n;j ++){
				if (cnt < n){
                    cout << j * k + i << " ";
                }
                else cout << j * k + i;
                cnt ++;
        }
    }
    return 0;
}

D-Rock Paper Scissors

题意:石头剪刀布,注意开long long

题解:要想分值最大,就让他先赢,后平,再输,这题坑了我很久,首先每自己看谁赢,所以写1赢,错了,之后每次做min运算更新rock,scissor,paper时这三个数值也会变化,因此不能直接加减,还要设置一个中间变量

# include <iostream>
# include <cmath>
# include <algorithm>

typedef long long ll;

using namespace std;

int main(){
    int t;
    ll r1, p1, s1, r2, p2, s2;
    cin >> t;
    while(t --){
        cin >> r1 >> p1 >> s1;
        cin >> r2 >> p2 >> s2;
        ll sum = 0;
        ll mi = 0;
        // win
        // 2 出 石头,1出 剪刀
        mi = min (r2,s1);
        sum += mi; 
        r2 -= mi;
        s1 -= mi;
        // 2 出 剪刀,1出 布
        mi = min (s2,p1);
        sum += mi;
        s2 -= mi;
        p1 -= mi;
        // 2 出 布, 1出 石头
        mi = min (p2,r1);
        sum += mi;
        p2 -= mi;
        r1 -= mi;
        // 平局
        // rock
        mi = min (r1,r2);
        r1 -= mi;
        r2 -= mi;
        // scissors
        mi = min (s1,s2);
        s1 -= mi;
        s2 -= mi;
        // paper
        mi = min (p1,p2);
        p1 -= mi;
        p2 -= mi;
        // fail
        sum -= (p2 + r2 + s2);
        cout << sum << endl; 
    }
    return 0;
}

H-Nihongo wa Muzukashii D

字符串替换,暴力写就可,但要注意字符为k的细节

// verb -> end with masu, te or de 
/*
    if end with imaus,chimaus or rimaus change to tte
    if end with mimaus, bimaus or nimaus, change to nde
    if end with kimasu, change to ite but if s is "ikimaus",change to "itte"
    if end with gimasu, change to ide
    if end with shimasu, change to shite
*/

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>

using namespace std;

typedef long long ll;

const int N = 1e5 + 10;

int main(){
    int t;
    cin >> t;
    while (t --){
        string s;
        cin >> s;
        ll n = s.length();
        if (s[n-1] == 'e' && s[n-2] == 't' || s[n-1] == 'e' && s[n-2] == 'd')
            cout << s << endl;
        else {
            if (s[n-6] == 'm' || s[n-6] == 'b' || s[n-6] == 'n'){
                for (int i = 0; i < n - 6; i ++)
                    cout << s[i];
                cout << "nde" << endl;
            }
            else if (s[n-6] == 'k'){
                 if (s == "ikimasu")
                     cout << "itte" << endl;
                else {
                    for (int i = 0; i < n - 6; i ++)
                        cout << s[i];
                    cout << "ite" << endl;
                }
             }  
            else if (s[n-6] == 'g'){
                for (int i = 0; i < n - 6; i ++)
                    cout << s[i];
                cout << "ide"<< endl;
            }
            else if (s[n-6] == 'h' && s[n-7] == 's'){
                for (int i = 0; i < n - 7; i ++)
                    cout << s[i];
                cout << "shite" << endl;
            }
            else if (s[n-6] == 'h' && s[n-7] == 'c'){
                for (int i = 0; i < n - 7; i ++)
                    cout << s[i];
                cout << "tte" << endl;
            }
            else if (s[n-6] == 'r'){
                for (int i = 0; i < n - 6; i ++)
                    cout << s[i];
                cout << "tte" << endl;
            }
            else {
                for (int i = 0; i < n - 5; i ++)
                    cout << s[i];
                cout << "tte" << endl;
            }
        }
    }
    return 0;
}

B-Hotpot

题意:n个人围着火锅转,他想吃什么,要是没有这个食材,就放,要是有,就吃了,并且幸福度+1

题解:看到这个题,直接想到了奇偶性,若是偶数倍的人喜欢吃一种食材,那么偶数倍的奇数位肯定吃不到,偶数倍的偶数位一定能吃到前一个人放的食材,如果是奇数倍的人喜欢一个食材,那n个人一圈下来吃到的食物就要反转了,第一圈能吃到,那么第二圈就吃不到了,偶数倍容易解决,但是奇数倍每一圈都要变化,在比赛过程中没有想到直接合成2*n的做法,最后还是靠队友ac了这个题,赛后看了队友代码和相关题解,感觉并不是很好理解,而且写的相对复杂,后来翻到一个很直观的写法,自己重现写了一遍ac代码

代码

# include <iostream>
# include <algorithm>
# include <string.h>

using namespace std;

typedef long long ll;

const int N = 1e5 + 10;

int eat[N*2];// 纪录喜欢吃的
int idx[N*2];// 用作标记
int num[N*2];// 记录是奇数位还是偶数位
int ans[N*2];// 记录满意度

int main(){
    int t;
    cin >> t;
    while (t --){
        int n, k;
        ll m;
        cin >> n >> k >> m;
        
        memset(eat,0,sizeof(eat));
        memset(idx,0,sizeof(idx));
        memset(num,0,sizeof(num));
        memset(ans,0,sizeof(ans));
        
        for (int i = 0; i < n; i ++){
            cin >> eat[i];
            eat[n+i] = eat[i];
        }
        //用round记录圈数,res纪录不足2n的圈数
        int round = m / (2*n);
        int res = m % (2*n);
        // 先处理round*2n圈
        for (int i = 0; i < 2*n; i ++){
            num[eat[i]] ++;
            if (num[eat[i]] % 2 == 0)
                idx[i] = 1;
            else idx[i] = 0;
            ans[i] += idx[i];
            // 这里直接乘上圈数
            ans[i] *= round;
        }
        // 处理剩下的不足2*n的情况
        for (int i = 0; i < res; i ++){
            num[eat[i]] ++;
            if (num[eat[i]] % 2 == 0)
                idx[i] = 1;
            else idx[i] = 0;
            ans[i] += idx[i];
        }
        // 求sum
        for (int i = 0; i < n; i ++){
            ans[i] += ans[i+n];
            cout << ans[i] << " ";
        }
        cout << endl;
    }
    return 0;
}

M-True Story

这题看了好久也没看懂这题说些什么话,找孙中远总算是翻译过来了qwq

题意:n个人有各自的速度s[i],到机场的距离都为x,原本是从0时出发,p0时登机,但是飞机会有k次延迟登机,这k次宣布延迟登机的时刻t[i],都会宣布会推迟到某一个时刻p[i],倒是这n个人有一个特点,就是只会在宣布推迟的那一时刻开始行动,比如说一开始从0时刻出发,5点登机,3点通知推迟到7点登机,那么这人就会从3点出发,即使他可能会延误飞机,也不会从一开始的0时刻出发,努力不一定会成功,但放弃一定会失败。

题解:简单模拟,定义初始时刻p0为max_time,再遍历k次延期的起止时间段,求出max(max_time,p[i] - t[i]),如果time*speed >= distance,就count++

#include <iostream>
#include <algorithm>
#include <string.h>

using namespace std;

const int N = 1e6 + 10;

typedef long long ll;

ll s[N];
ll t[N];
ll p[N];

int main(){
    ll n, k, x, p0;
    ll cnt = 0;
    cin >> n >> k >> x >> p0;
    ll max_time = p0;
    //cout << max_time;
    for (ll i = 0; i < n; i ++)
        cin >> s[i];
    for (ll i = 0; i < k; i ++)
        cin >> t[i];
    for (ll i = 0; i < k; i ++)
        cin >> p[i];
    for (ll i = 0; i < k; i ++)
        max_time = max (max_time,p[i] - t[i]);
    for (ll i = 0; i < n; i ++)
        if (s[i] * max_time >= x)
            cnt ++;
    cout << cnt;
    return 0;
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM