AtCoder Beginner Contest 109(ABC109)

ABC

A – ABC333

A – ABC333 (atcoder.jp)

Cが3通りしかないため、全通り判定する。でもいいのですが、偶奇の性質を使うことでスラっと書けます。
偶奇同士の掛け算の答えは以下のようになります。

偶*偶=偶
偶*奇=偶
奇*奇=奇

つまり、A*B*Cが奇になるには3つが奇である必要があります。
Cは1,2,3好きに選べるので無視して、A,Bの2つ両方が奇かどうかを見ればOKです。

#include<bits/stdc++.h>
//#include<atcoder/all>

using namespace std;
//using namespace atcoder;

int main(){
    int A,B,C;
    cin>>A>>B>>C;
    if(A%2==0||B%2==0) cout<<"No"<<endl;
    else cout<<"Yes"<<endl;
}

B – Shiritori

B – Shiritori (atcoder.jp)

ちょっとややこしめ、YESの条件文としては以下です。

  1. W2~WNにおいて、Wiの最初の文字とWi-1の最後の文字が等しい
  2. W1~WNにおいて、同じ文字が出現しない

N=100なので書き方は色々あると思いますが、私は条件を満たすものをsetに放り込んで、setのsizeがNと等しいかで判定しました。(setは重複が登録されないので、2の条件がサボれます。)

#include<bits/stdc++.h>
//#include<atcoder/all>

using namespace std;
//using namespace atcoder;

int main(){
    int N;
    cin>>N;

    set<string> s;
    string befS;
    cin>>befS;
    s.insert(befS);
    for(int i=0;i<N-1;i++){
        string S;
        cin>>S;
        if(befS[befS.size()-1]==S[0]) s.insert(S);
        befS=S;
    }

    if(s.size()==N) cout<<"Yes"<<endl;
    else cout<<"No"<<endl;
}

C – Skip

C – Skip (atcoder.jp)

Xを0とした場合、+D,-Dして移動して辿り着ける場所は、D,2D,3D,4D…-D,-2D,-3D,-4D….とDの倍数になります。
なので、この問題は各x[i]とXの距離に対して、最大の約数を求めるものとなります。

#include<bits/stdc++.h>
//#include<atcoder/all>

using namespace std;
//using namespace atcoder;

int main(){
    int N,X;
    cin>>N>>X;

    int sx[N];
    for(int i=0;i<N;i++){
        int x;
        cin>>x;
        sx[i]=abs(X-x);
    }

    vector<int> ans;
    for(int i=2;i<sqrt(sx[0])+2;i++){
        while(sx[0]%i==0){
            sx[0]/=i;
            ans.push_back(i);
        }
    }
    if(sx[0]!=0) ans.push_back(sx[0]);

    for(int i=1;i<N;i++){
        vector<int> tmp;
        for(int j=0;j<ans.size();j++){
            if(sx[i]%ans[j]==0){
                sx[i]/=ans[j];
                tmp.push_back(ans[j]);
            }
        }
        ans=tmp;
    }

    int b=1;
    for(int i=0;i<ans.size();i++) b*=ans[i];

    cout<<b<<endl;
}

かなり面倒なコードを書きましたが、”最大の約数を求める”場合、最大公約数を使うと楽です。

#include<bits/stdc++.h>
//#include<atcoder/all>

using namespace std;
//using namespace atcoder;

int gcd(int a,int b){
    if(a<b) return gcd(b,a);
    if(b==0) return a;
    return gcd(b,a%b);
}
int main(){
    int N,X;
    cin>>N>>X;

    int gc;
    cin>>gc;
    gc=abs(gc-X);
    for(int i=0;i<N-1;i++){
        int x;
        cin>>x;
        gc=gcd(gc,abs(X-x));
    }

    cout<<gc<<endl;

}

D – Make Them Even

D – Make Them Even (atcoder.jp)

偶数枚コインが置かれた場所を最大化する問題です。
任意の一筆書きのルートで、奇数枚なら1枚次に送る。ということを繰り返せば良さそうです。

    1 2 3 4 5 6 7 8 9 左から右に見ていく
i=0 0 3 3 4 5 6 7 8 9 奇数なので右に送る 
i=1 0 2 4 4 5 6 7 8 9 奇数なので右に送る
i=2 0 2 4 4 5 6 7 8 9 偶数なのでそのまま
i=3 0 2 4 4 5 6 7 8 9 偶数なのでそのまま
i=4 0 2 4 4 4 7 7 8 9 奇数なので右に送る
i=5 0 2 4 4 4 6 8 8 9 奇数なので右に送る
i=6 0 2 4 4 4 6 8 8 9 偶数なのでそのまま
i=7 0 2 4 4 4 6 8 8 9 偶数なのでそのまま
i=8 0 2 4 4 4 6 8 8 9 奇数だけどゴールなので無視

最後が奇数になりますが、コインの総量が奇数なのでどうやっても残ります。(すべてのマスが偶数枚の場合、偶数同士の足し算は偶数なので総量も偶数になるはず)
最後を除く一筆書きのルートが全て偶数で均せるため最大化できます。

#include<bits/stdc++.h>
//#include<atcoder/all>

using namespace std;
//using namespace atcoder;

int gcd(int a,int b){
    if(a<b) return gcd(b,a);
    if(b==0) return a;
    return gcd(b,a%b);
}
int main(){
    int H,W;
    cin>>H>>W;

    int a[H][W];
    for(int i=0;i<H;i++){
        for(int j=0;j<W;j++){
            cin>>a[i][j];
        }
    }

    vector<int> a1,a2,a3,a4;
    for(int i=0;i<H;i++){
        if(i%2==0){
            for(int j=0;j<W-1;j++){
                if(a[i][j]%2==1){
                    a1.push_back(i);
                    a2.push_back(j);
                    a3.push_back(i);
                    a4.push_back(j+1);
                    a[i][j+1]++;
                }
            }
            if(i!=H-1&&a[i][W-1]%2==1){
                a1.push_back(i);
                a2.push_back(W-1);
                a3.push_back(i+1);
                a4.push_back(W-1);
                a[i+1][W-1]++;
            }
        }
        else{
            for(int j=W-1;j>=1;j--){
                if(a[i][j]%2==1){
                    a1.push_back(i);
                    a2.push_back(j);
                    a3.push_back(i);
                    a4.push_back(j-1);
                    a[i][j-1]++;
                }
            }
            if(i!=H-1&&a[i][0]%2==1){
                a1.push_back(i);
                a2.push_back(0);
                a3.push_back(i+1);
                a4.push_back(0);
                a[i+1][0]++;
            }
        }
    }
    cout<<a1.size()<<endl;
    for(int i=0;i<a1.size();i++){
        cout<<a1[i]+1<<" "<<a2[i]+1<<" "<<a3[i]+1<<" "<<a4[i]+1<<endl;
    }
}

コメント

タイトルとURLをコピーしました