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