Codeforces Round #847 (Div. 3)

前言

重回程式設計第一天…

因為種種原因停更好久,直到最近,我決定重新開始寫題目。這次的題目選自 https://codeforces.com/contest/1790 ,剛回來想用 Div3 試個手感,沒想到也卡了許久。

本文

言歸正傳,本質上這還是一個分享網站。那我今天用了三個小時總共寫出5題(共7題)。以下是提示、想法、與程式碼的分享。

pA Polycarp and the Day of Pi

簡單說就是求前30位的圓周率他寫對幾位,比較需要注意的是範例已經給一個完整的圓周率。

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

// a 是輸入
string ans="314159265358979323846264338327",a;

void solve(){
    cin>>a;
    int same=0;
//  逐位判斷
    for(int i=0;i<a.size();++i){
        if(a[i]==ans[i]){
            same++;
        }else{
            break;
        }
    }
    cout<<same<<"\n";
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);

    int t;
    cin>>t;
    while(t--){
        solve();
    }
}

pB Taisia and Dice

題目概要

給你三個數字 n, s, r ,n是骰子數,s是點數總和,r則是扣掉一個最大的骰子點數後的點數總和。求一個可能的點數序列。

提示1

最大的點數是s-r

提示2

這序列沒有規定骰子點數不能重複

想法

綜合兩個提示,我們可以發現。盡量先用最大點數(s-r),最後都用1點,中間再補差額就可以了。程式碼的表達正好相反。

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

void solve(){
    int n,s,r;
    cin>>n>>s>>r;
    int d=s-r,sum=0;
    for(int i=1;i<=n;++i){
//      n-i+1 = 剩餘骰子數
        if(n-i+1==s-sum){
            cout<<1<<" ";
            sum++;
        }else if(n-i<s-sum && s-sum-d<n-i){
            cout<<s-sum-(n-i)<<" ";
            sum+=s-sum-(n-i);
        }else{
            cout<<d<<" ";
            sum+=d;
        }
    }
    cout<<"\n";
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);

    int t;
    cin>>t;
    while(t--){
        solve();
    }
}

pC

題目概述

有一個1-n都出現過一次的序列讓你猜,然後不按順序的給你n個數列,每個數列都是原本的序列但會刪除一個元素。求原序列。

例如:

3
2 3
1 3
1 2

則原序列為1 2 3。

提示1

只需要兩個序列就可以求出完整的。

提示2

頭尾的元素是關鍵。

想法

其實找到兩個關鍵序列就可以了,就是刪掉第一個和刪掉最後一個的。

例如:

4 2 1
4 2 3
2 1 3
4 1 3

就只需要

4 2 1
  2 1 3

就可以還原整個序列。

那至於如何尋找,如提示2所述,關注第一個與最後一個元素。不同的那個就是我們要的。

程式碼
#include<bits/stdc++.h>
using namespace std;
// s[i] 序列的第一個數字為i的次數
// sr[i] 最後一個
// bd[i][j] 存讀進來的資料
// f 第一個元素,r則是最後一個
// d,c就是我們要找的那兩個序列
int bd[105][105],s[105],sr[105],f,d,r,c;

void solve(){
    int n;
    cin>>n;
    for(int i=1;i<=n;++i){
        for(int j=1;j<n;++j){
            cin>>bd[i][j];
        }
    }
//  初始化
    f=-1;
    r=-1;
    for(int i=1;i<=n;++i){
        s[i]=0;
        sr[i]=0;
    }
//  找f,r
    for(int i=1;i<=n;++i){
        s[bd[i][1]]++;
        sr[bd[i][n-1]]++;
        if(s[bd[i][1]]>1){
            f=bd[i][1];
        }
        if(sr[bd[i][n-1]]>1){
            r=bd[i][n-1];
        }
    }
//  找不同於f,r的
    for(int i=1;i<=n;++i){
        if(bd[i][1]!=f){
            d=i;
        }
        if(bd[i][n-1]!=r){
            c=i;
        }
    }

    for(int i=1;i<=n-1;++i){
        cout<<bd[c][i]<<" ";
    }
    cout<<bd[d][n-1];

    cout<<"\n";
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);

    int t;
    cin>>t;
    while(t--){
        solve();
    }
}

pD Matryoshkas

題目概述

給你一堆俄羅斯娃娃的大小,問你原來最少有幾組。其中,每一組的娃娃大小都必須要是連續整數。例如1 2 3。

提示1

能疊越多層越好。

提示2

動態的資料增刪操作。

想法

能疊越多層越好,因此,每一次都用while嘗試往上疊。那就需要尋找一個大小+1的娃娃存不存在。可以使用multiset或是map,而我選map。

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

void solve(){
    int n,a,sum=0;
    cin>>n;
    map<int,int> mp;
    for(int i=0;i<n;++i){
        cin>>a;
        mp[a]++;
    }

    for(auto e:mp){
        while(e.second>0){
            int tp=e.first;
            while(mp.count(tp+1) && mp[tp+1]>0){
                mp[tp+1]--;
                tp++;
            }
            sum++;
            e.second--;
        }
    }
    cout<<sum;

    cout<<"\n";
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);

    int t;
    cin>>t;
    while(t--){
        solve();
    }
}

pE Vlad and a Pair of Numbers

題目概述

給你一個x,找到a,b滿足 a \oplus b=\frac{a+b}{2}=x,其中  \oplus是xor,也就是C++上的

a^b;

第五題最後有偷看詳解,使用的做法請見-> https://codeforces.com/blog/entry/111948

發佈留言