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

AtCoder Beginner Contest 215 個人題解

AtCoder Beginner Contest 215 個人題解

比賽連結:AtCoder Beginner Contest 215

前言:這是小飛龍在AtCoder的的一場比賽

AtCoder題面好評!簡單明瞭,絲毫沒有拖泥帶水,這讓英文水平菜的一批的小飛龍很是欣慰o( ̄▽ ̄)ブ

A題 Your First Judge

題目大意:

一句話題意,給出一串字串,判斷是否和Hello,World!完全匹配,如果是輸出AC,否則輸出WA

思路解析:

難度高於且僅高於輸出hello world!(也就是符合小飛龍目前水平的題)

AC程式碼:

#include<bits/stdc++.h>
using namespace std;
int main(){
    string s;
    cin>>s;
    cout<<(s=="Hello,World!"?"AC":"WA")<<endl;
}

B題 log2(N)

題目大意:

給出一個數 \(n\) , \(1<=n<=10^{18}\) ,輸出 \(log_2(n)\)

思路解析:

直接模擬乘 \(2\) 即可(直接用Math庫的 \(log_2()\)\(WA\) 的風險,具體反面教材 @tbw)

AC程式碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int main(){
    
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);

    ll n,now=1;
    cin>>n;

    for(ll i=1;;i++){
        now*=2;
        if(now>n){
            cout<<i-1<<endl;
            break;
        }
    }
}

C題 One More aab aba baa

題目大意:

給出一串字串 \(S\) 和它的長度,輸出字典序第 \(K\) 小的字串排列

思路解析:

由於我們可以看到 \(1<=|S|<=8\) ,所以我們可以對 \(S\) 排序後直接用 \(STL\) 中的next_permutation()來列舉他的排列,輸出第 \(K\) 小排列即可

AC程式碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int n;
char s[maxn];
int main(){
    
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);

    cin>>s>>n;
    int sz=strlen(s),sum=0;
    sort(s,s+sz);
    do{
        sum++;
        if(sum==n){
            for(int i=0;i<sz;i++)cout<<s[i];
            break;
        }
    }
    while(next_permutation(s,s+sz));
}

D題 Coprime 2

題目大意:

給出一長度為 \(N\) 的序列 \(A_i\) ,和一個正整數 \(M\) ,我們需要找到所有的 \(k\) 且同時滿足 \(1<=k<=M\)\(gcd(A_i,k)=1(1<=i<=N)\)

思路解析:

根據題意我們可以發現,我們需要的k和陣列中的每一個元素的 \(gcd\) 都為 \(1\) ,所以我們很容易想到從序列中每一個數的約數下手,可是我們處理完約數後該怎麼辦呢?

這時候,我們很容易想到,對於每一個約數以及約數的倍數,都一定不可能作為我們 \(k\) 的候選值,我們要做的就是在 \(1-M\) 中刨除這些數,是不是感覺在哪裡見過?確實,這就是我們晒素數使用的線性篩,可以使我們這道題的複雜度大大降低(具體反面教材再次 @tbw)

另外,對於序列中的所有約數我們可以判一下重後再處理,因為他的玩味並不是很大,所以顯然約數的數量並不是很大,所以複雜度並不高

AC程式碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;

int vis[maxn],p[maxn];
int st[maxn];

vector<int> get_divisiors(int n)
{
    vector<int> res;
    for(int i = 1; i <= n / i; i ++ )
        if(n % i == 0)
        {
            res.push_back(i);
            if(i != n / i) res.push_back(n / i);
        }
    sort(res.begin(), res.end());
    return res;
}

vector<int >ans[maxn];

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

    int n,m,op;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>op;
        ans[i]=get_divisiors(op);
        for(int k=0;k<ans[i].size();k++){
            if(ans[i][k]==1)continue;
            if(st[ans[i][k]])continue;
            st[ans[i][k]]=1;
            for(int j=ans[i][k];j<=m;j+=ans[i][k]){
                if(vis[j])continue;
                vis[j]=1;
            }
        }
    }
    int top=0;
    for(int i=1;i<=m;i++)if(!vis[i])p[++top]=i;
    cout<<top<<endl;
    for(int i=1;i<=top;i++)cout<<p[i]<<endl;
}

E題 Chain Contestant

隊友寫了我就不寫了(逃)

戳這裡檢視題解 @tbw831

F題 Dist Max 2

題目大意:

給出平面內n個點的座標,定義兩點之間的距離為 \(min(|x_i-x_j|,|y_i-y_j|)\) ,輸出兩個不同點的距離的最大值

思路解析:

從問題來看,求 \(min\) 的最大值,很容易想到用二分答案來解決這道題,這樣問題就轉化為了判定所有點中是否存在兩個不同點滿足距離大於等於 \(mid\) ,二分即可

那麼如何判定是否存在呢?我們可以用單調佇列來判斷,複雜度 \(O(n)\) ,總複雜度 \(O(nlogn)\)

AC程式碼:

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int maxn=1e5+5;

vector<pii>a;

int check(int mid){
    queue<pii>q;
    int minn=1e9+7,maxx=0;
    for(int i=0;i<a.size();i++){
        while(q.size()){
            if(q.front().first>a[i].first-mid)break;
            minn=min(minn,q.front().second);
            maxx=max(maxx,q.front().second);
            q.pop();
        }
        if(minn<=a[i].second-mid||maxx>=a[i].second+mid)return 1;
        q.push(a[i]);
    }
    return 0;
}

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

    int n;
    cin>>n;

    for(int i=1;i<=n;i++){
        int x,y;
        cin>>x>>y;
        a.push_back({x,y});
    }

    sort(a.begin(),a.end());

    int l=0,r=1e9+7;

    while(l < r){
        int mid=l+r+1>>1;
        if(check(mid))l=mid;
        else r = mid - 1;
    }
    cout<<l<<endl;
}

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