1. 程式人生 > 其它 >AtCoder Beginner Contest 216 個人題解

AtCoder Beginner Contest 216 個人題解

AtCoder Beginner Contest 216 個人題解

比賽連結:AtCoder Beginner Contest 216

每篇一圖

A題 Signed Difficulty

題目大意:

給出一個小數,根據小數部分改寫 \(+,-\)

思路解析:

直接判斷即可

AC程式碼:

#include<bits/stdc++.h>
using namespace std;
int main(){
    int x,y;
    scanf("%d.%d",&x,&y);
    if(y<=2)cout<<x<<"-"<<endl;
    else if(y<=6)cout<<x<<endl;
    else cout<<x<<"+"<<endl;
}

B題 Same Name

題目大意:

給出 \(n\) 個人的名字,每個人的名字由兩部分組成,問是否有重名的人

思路解析:

  • 暴力列舉匹配
  • STL-map判斷

AC程式碼:

暴力

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
struct node{
    string x,y;
}s[maxn];
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>s[i].x>>s[i].y;
    int flg=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i==j)continue;
            if(s[i].x==s[j].x&&s[i].y==s[j].y)flg=1;
        }
    }
    if(flg)cout<<"Yes"<<endl;
    else cout<<"No"<<endl;
}

map

#include<bits/stdc++.h>
using namespace std;
map<string,map<string,int> >a;
string s,t;
int n;
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>s>>t;
		if(a[s][t]){
			cout<<"Yes"<<endl;
			return 0;
		}
		a[s][t]=1;
	}
	cout<<"No"<<endl;
}

C題 Many Balls

題目大意:

有一個盒子,你可以進行兩種操作:1.往盒子裡放一個球 2.使盒子裡的球翻倍
問一個可行的操作方案使盒子裡的球從 \(0\)\(n\) ,操作最多 \(120\)

思路解析:

我們很容易想到可以從 \(n\) 往回推,這樣操作 \(1\) 就變成了 \(/2\) ,操作 \(2\) 就變成了 \(-1\) ,當\(n\) 為偶數,就可以 \(/2\) 當 ,\(n\) 為奇數就可以 \(-1\) ,直到盒子裡的球為 \(0\)

AC程式碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
    ll n;
    cin>>n;
    string ans;
    while(n){
        if(n%2==0){
            ans+='B';
            n/=2;
        }
        else{
            ans+='A';
            n--;
        }
    }
    for(int i=ans.size()-1;i>=0;i--)cout<<ans[i];
}

D題 Pair of Balls

題目大意:

我們有 \(n\) 種顏色的球,每種顏色有兩個球,總共有 \(2n\) 個球,這些球被放在 \(m\) 個棧中,每次只能從兩個不同棧頂取出相同顏色的球,問是否可以把球全部取出(好像消消樂)

思路解析:

首先我們思考,很直觀的考慮,什麼時候會不能達成目的:
靈魂畫手上線:

由題意我們很容易看出,如果要想清空一個棧的話每個棧頂的數字一定需要先於他下面的數刪除,所以這就形成了拓撲關係。
在觀察資料,我們又可以發現由於每個數字存在兩個,所以以每個數字為節點,至多向外連兩條有向邊,我們就可以把問題轉化為了有向圖的拓撲排序來處理。

AC程式碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=4e5+5;
int e[maxn],h[maxn],nex[maxn],id;
int ans,in[maxn];
queue<int>q;
void add(int x,int y){
    e[++id]=y;
    nex[id]=h[x];
    h[x]=id;
}
int main(){
    int n,m;
    cin>>n>>m;
    for(int j=1;j<=m;j++){
        int k,pre,x;
        cin>>k>>pre;
        for(int i=2;i<=k;i++){
            cin>>x;
            add(x,pre);
            in[pre]++;
        }
    }
    for(int i=1;i<=n;i++){
        if(in[i]==0)q.push(i);
    }

    while(q.size()){
        int top=q.front();
        q.pop();
        ans++;
        for(int i=h[top];i;i=nex[i]){
            int j=e[i];
            in[j]--;
            if(in[j]==0)q.push(j);
        }
    }
    if(ans==n)cout<<"Yes"<<endl;
    else cout<<"No"<<endl;
}

E題 Amusement Park

題目大意:

給你 \(n\) 個數,你可以選擇 \(k\) 次,每次選擇一個數後這個數就會 \(-1\) ,問你能得到選擇數的和的最大值

思路解析:

首先我們考慮暴力的做法:直接把數都扔到set裡,每次取最大然後讓他-1再把它扔回去就行了,但是這麼做穩T
如何優化:推一推,手搓一下就完了

AC程式碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
ll n,k,a[maxn],cnt,ans;
bool cmp(ll x,ll y){
    return x>y;
}
int main(){
    cin>>n>>k;
    for(int i=1;i<=n;i++)cin>>a[i];
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++){
        ll x=a[i]-a[i+1];
        if(cnt+i*x<=k){
            ans+=(a[i]+a[i+1]+1)*x/2*i;
            cnt+=i*x;
        }
        else{
            k-=cnt;
            ans+=(a[i]+a[i]-(k/i)+1)*(k/i)/2*i;
            ans+=(k%i)*(a[i]-(k/i));
            break;
        }
    }
    cout<<ans<<endl;
}

F題 Amusement Park

題目大意:

給你兩個長度為 \(n\) 陣列 \(A\)\(B\) ,分別對應位置 \(1-n\) ,問有多少個S of {1,2,...,n}的子集滿足 \(max_{i\in S}A_i \geq \sum_{i\in S}B_i\)

思路解析:

AC程式碼:


G題 01Sequence

題目大意:

你需要構造一個 \(01\) 串,滿足給出的每個 \(L_i,R_i,X_i,\)\([L,R]\) 中至少有 \(X\)\(1\)
輸出滿足條件的 \(01\) 串且 \(01\) 串中 \(1\) 最少

思路解析:

AC程式碼:


推廣一波小飛龍部落格:戳這裡@不會飛的小飛龍

本文來自部落格園,作者:不會飛的小飛龍,轉載請註明原文連結:https://www.cnblogs.com/xiaofeilong7816/p/15203739.html