ZZJC新生訓練賽第九場題解

udiandianis發表於2024-10-25

A題

思路

重點在於題目操作蘊含的奇偶數關係,一個偶數可以和一個奇數一起刪除,兩個奇數可以一起刪除。

程式碼

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin>>n;
    vector<int>ar(n);
    int j=0,o=0;//j代表奇數的個數,o代表偶數的個數
    for(int i=0;i<n;i++){
        cin>>ar[i];
        if(ar[i]&1){
            j++;
        }else{
            o++;
        }
    }
    if(o>j)cout<<max(0,o-j);
    else{
        if((j-o)&1){
            cout<<1;
        }else{
            cout<<0;
        }
    }
}

B題

思路

只需把遞迴式子拆開來,等差數列求個和,每步操作%P防止超出精度就行。

程式碼

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    #define int long long
    int t;
    cin>>t;
    int p = 998244353;
    while(t--){
        int a,x;
        cin >> a >> x;
        if(x==1){
            cout<<a%p<<'\n';
            continue;
        }
        cout<<(x*(x-1)/2)%p*a%p*a%p<<'\n';
    }
}

C題

思路

排序貪心即可,找在x範圍內最大的ai,和它前面共有幾個數。

程式碼

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n,m;
    cin>>n>>m;
    vector<int>a(n);
    for(auto &x:a){
        cin>>x;
    }
    sort(a.begin(),a.end());
    int cnt=0;
    int maxn=0;
    for(auto x:a){
        if(x<=m){
            cnt++;
            maxn=x;
        }
    }
    cout<<cnt<<" "<<m-maxn<<'\n';
}

D題

思路

BFS模板題,dxdy裡存四個方向,寬度優先搜尋,每一個向外擴充套件,最先搜到的就是最少的步數。

程式碼

#include<bits/stdc++.h>
using namespace std;

typedef pair<int, int> PII;
const int N = 1010;
int n, m;
char g[N][N];
int d[N][N];

int bfs()
{
    queue<PII> q;

    memset(d, -1, sizeof d);
    d[0][0] = 0;
    q.push({0, 0});

    int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

    while (q.size())
    {
        auto t = q.front();
        q.pop();
        for (int i = 0; i < 4; i ++ )
        {
            int x = t.first + dx[i], y = t.second + dy[i];
            if (x >= 0 && x < n && y >= 0 && y < m && g[x][y] !=g[t.first][t.second] && d[x][y] == -1)
            {
                d[x][y] = d[t.first][t.second] + 1;
                q.push({x, y});
            }
        }
    }

    return d[n - 1][m - 1];
}

int main()
{
    cin >> n >> m;
    for (int i = 0; i < n; i ++ )
        for (int j = 0; j < m; j ++ )
            cin >> g[i][j];

    cout << bfs() << endl;

    return 0;
}

E題

思路

上一題的構造方法有很多,重點在於構造出一條滿足條件的路徑,且把其他路堵住,程式碼很shit。

程式碼

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n,m;
    cin>>n>>m;
    char g[n+1][m+1];
    int cnt=0;
    bool flag=false;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(i==n){
                g[i][j]='a'+cnt;
                if(j%2!=0)cnt++;
            }
            else {
                g[i][j]='a'+cnt;
                if(j%2==0)cnt++;
            }
            if(cnt==26)cnt=0;
        }
    
        if(cnt==26)cnt=0;
    }
    if(g[n-1][2]==g[n][2]){
        int p=g[n-1][2]-'a';
        p++;
        if(p==26)p=0;
        g[n][3]='a'+p;
        p++;
        if(p==26)p=0;
        g[n-1][3]='a'+p;
        p++;
        for(int i=4;i<=m;i++){
            g[n-1][i]='a'+p;
            p++;
            if(p==26)p=0;
        }
        g[n][m]='a'+p;
    }


    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cout<<g[i][j];
        }
        cout<<'\n';
    }
}

F題

思路

簽到,只要看每個後面是否有大寫,有大寫代表這裡需要一次操作,答案++。

程式碼

#include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        string ss;
        cin>>ss;
        int cnt=0;
        for(int i=0;i<ss.size()-1;i++){
            if(ss[i+1]<='Z'&&ss[i+1]>='A'){
                cnt++;
                i++;
            }
        }
        cout<<cnt<<"\n";
}

G題

思路

依舊是排序貪心,只要剩餘數量大於k個就取就行。

程式碼

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    #define int long long
    int n,k;
    cin>>n>>k;
    vector<int>ar(n+1);
    int sm=0;
    for(int i=1;i<=n;i++){
        cin>>ar[i];
        sm+=ar[i];
    }
    sort(ar.begin()+1,ar.end());
    int sum=0;
    int cnt=0;
    if(sm%k==0){
        cout<<0;
        return 0;
    }
    for(int i=n;i>0;i--){
        sum+=ar[i];
        cnt++;
        if(sum>sm-sm/k*k){
            break;
        }
    }
    cout<<cnt;
}

H題

思路

利用set判斷是否這位數出現過,把各個特殊情況判一下,是否是一個排列,否的話,n大於1,就把第二位的值改成第一位,n==1時,就把第一位的值改成2。

程式碼

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin>>n;
    vector<int>ar(n);
    set<int>st;
    bool flag=true;
    for(int i=0;i<n;i++){
        int xp;
        cin>>xp;
        if(xp>n)flag=false;
        if(st.count(xp)){
            flag=false;
        }
        else st.insert(xp);
        ar[i]=xp;
    }
    if(!flag)cout<<0<<'\n';
    else if(n!=1){
        cout<<1<<'\n'<<2<<' '<<ar[0]<<'\n';
    }
    else cout<<1<<'\n'<<1<<' '<<2;
}

相關文章