1
0

More than 3 years have passed since last update.

【ABC168へ参加してみた】在宅勤務になったのでマネジメント系SEが競技プログラミング始めてみた。#7 -解説も-

Last updated at Posted at 2020-05-17

今回の記事

ABC168に参加しました。
今回もB問題までしか解けず。。(いやいやいつまでやねん..ほんと悔しい)
ただC問題もコンテスト終了後に、Twitterで助けてもらって理解したので
今回はC問題まで解説も合わせて記載します。

またTwitterで色々聞いたりとかもあるので、
とうとうAtcoderアカウントを晒します。
いじめないでくださいね(笑)

◆私のAtcoderアカウント
https://atcoder.jp/users/MakotoMM?lang=ja
◆Twitterアカウント
https://twitter.com/Makoto_M_coder

解説に飛ぶ方はこちら

当日の解答結果

今回もB問題しか解けませんでした。。。(泣)
後述しますが、C問題は一部条件を見落としており、それに気づけずでした。。
気づけたら久しぶりの3完(ABCの3問正解)だったのに。。。
スクリーンショット 2020-05-17 23.55.57.png

パフォーマンスについて

パフォーマンスもダメダメですね。。
んーーどうにかせんといかん。。
スクリーンショット 2020-05-17 23.56.11.png

振り返りと反省

1.Atcoderの過去問漁り

Atcoderの過去問を漁り始めました。
ひとまずABC156までのABC問題を解いてみました。
※そして公開用にAtcoderアカウント名を変更したのですが、AtcoderProblemが引継ぎされてなさげ。。。
(追記)
翌朝確認するとしっかり更新されてました。バッチかな、、Twitterにも一部処理の見直しをやったともあったので理由は不明確ですが安心しました!)

2.アルゴリズムの勉強をスタート

いつものとおりこちらのページを参考にしてアルゴリズムを勉強し始めました。
いま7問目まで解きました。
正直難しい。。。

問題解説

今回は冒頭にも記載しましたがC問題まで解説します!!
そして問題名がいつもと違った感じだったからびっくりしたのは内緒。

A問題:∴ (Therefore)

問題文抜粋
スクリーンショット 2020-05-18 0.13.29.png

解説

A問題については、数字について場合分けが必要となります。
1の位を求めるには「%10」を使って10の余りを計算する必要があります。

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

int main(void){
    int N, ans=0;
    cin >> N;

    if(N%10==0 || N%10==1 || N%10==6 || N%10==8)
      cout << "pon" << endl;
    else if(N%10==3)
      cout<< "bon" <<endl;
    else
      cout<< "hon" <<endl;

    return 0;
}

B問題:... (Triple Dots)

問題文抜粋
スクリーンショット 2020-05-18 0.13.38.png

解説

B問題については問題文通りに入力の「K」と「S」の長さを比較して対応します。
またSの長さがKを上回ってる場合について行う抜き出しについては、
「substr」を使うか、もしくは単純に抜き出すかですね。
※私は「substr」を使わずに、単純に抜き出しました(笑)

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

int main(void) {
    int K, ans=0;
    string S;

    cin >> K;
    cin >> S;

    string tmp;
    if(S.size()<=K){ //Sの長さよりもKが大きければ
      cout << S <<endl;
      return 0;
    }
    else{ //Sの長さよりもKが小さければ
      for(int i=0; i<K; i++)   tmp += S[i]; //K文字分抜き出す
      tmp += "..."; //「...」を後ろに足す
    }

    cout << tmp << endl;

    return 0;
}

C問題:: (Colon)

問題文抜粋
スクリーンショット 2020-05-18 0.21.31.png

解説

時計の問題です。
時計の中で時間を表す針「時針」の長さをAcm、分を表す針「分針」の長さをBcmが与えれます。
その長さを元に、時針と分針を使ってできる三角形の残りの辺の長さを求めます。
スクリーンショット 2020-05-18 0.48.42.png

この時、数学で習った(もしくは習うであろう)三角関数の余弦定理を用いて
線の長さを求めます。

そのためには時針、分針で形成される角度を求める必要があります。
0時を基準に時針、分針それぞれの角度を求めてあげ、その差分が時針、分針で形成される角度となります。
ただし注意したいのが、時針です。
時針については、例えば下図のように8:40の場合は8:00丁度から40分進んだ際の角度を求めてあげる必要があります。
スクリーンショット 2020-05-18 0.46.06.png
また同じように分針の角度も求めてあげます。
また忘れてはいけないのが、時針と分針が重なる場合です。
その場合は長い針から短い針の長さを引くだけとなるので、条件分岐が必要となります。
※私はこの分岐を忘れてしまってました。。

あ、加えてC++では三角関数は度数法ではなく弧度法としてラジアンを入力する必要がありますのでご注意ください。
ラジアンって何?美味しいの?って人はこちら

problemC.cpp

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

int main(void) {
    double A, B , H , M;
    double ans;
    cin >> A >> B >> H >> M;

    double ang_A,ang_B;
    ang_A = 30.0*H + 0.5*M; //「360/12=30」「360/12/60=0.5」
    ang_B = 6.0*M; //「360/60=6」

    if(ang_A==ang_B) { //時針と分針の角度が一緒だったら
      cout << abs(A-B) << endl; //A-Bの絶対値をとる
      return 0;
    }

    double rad;
    rad = (ang_A-ang_B)*M_PI/180.0; //度数からラジアンへ変換
    ans = A*A + B*B - 2.0*A*B*cos(rad); //余弦定理
    printf("%.10lf\n",sqrt(ans) ); //有効桁数を意識してprintfで出力

    return 0;
}

今後に向けて

いやーC問題が今回も解けなくてだいぶ落ち込んでます。
成果に出るのはまだまだ先かもしれませんが、改めて気合入れていきたいと思います。

最後に

いかがだったでしょうか?
見ても解らないやもう少しこうすると良いのではないか?といった暖かい言葉ドシドシお待ちしています。
またTwitterも是非お気軽にフォローしてください。
https://twitter.com/Makoto_M_coder

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0