しがない元高専生の競プロ日記

AtCoderとかいろいろ解いてく

Cafecoder(元kakecoder) Tea Break 002 非公式解説&感想

Tea Break2お疲れさまでした
少し遅れて参加して3WA21分全完でした。(ランキング機能ないのでDの提出時間の情報しかないです)
f:id:honehaniwa:20191113213247p:plain AtCoder等のRatedコンは基本C++で参加してるのですが、卒業研究やら機械学習やらでPythonを触り始めたので 実装力をつけよう程度にPythonで解きました。
やっぱりこの難易度帯(AtCoderの平成ABC-Cくらい)がやってて楽しいです。

Green - Semiprime-like (100)

Nがa×b(a,b>=2)の積で表せるかの問題。
2~N-1の間で余りが0になるか判定すれば良さそうですね。
C++の例

#include<iostream>
using namespace std;
int main(){
  int N;
  cin>>N;
  bool flag = false;
  for(int i=2; i<N; i++){
    if(N%i == 0){
      flag = true;
    }
  }
  if(flag) cout << "Yes" << endl;
  else cout << "No" << endl;
}

Pythonの例

N = int(input())
flag = False
for i in range(2,N):
  if N%i == 0:
    flag = True
print('Yes' if flag else 'No')

Ceylon - Trick of Treat (200)

4つの飴を均等に分けることができるか?という問題。
A~Dの総和を求めて4で割り切れるか判定すれば良さそう
C++の例

#include<iostream>
using namespace std;
int main(){
  int A,B,C,D;
  cin >> A >> B >> C >> D;
  int sum = A+B+C+D;
  cout << ((sum%4 == 0)? "Yes":"No") << endl;//つい先日話題になった三項演算子
}

Pythonの例

l=list(map(int,input().split()))
print('Yes' if sum(l)%4 == 0 else 'No')

今回は総和を求めたいだけなのでListに格納してsum(List)とすれば楽に総和を求められます。

Earlgray - 最小全域木?なにそれおいしいの?

ぱっと見で難易度高そうな問題。でもそこで諦めてはいけない
f:id:honehaniwa:20191113220348p:plain
ここで、入力例1の図を見てみると、
f:id:honehaniwa:20191113220519p:plain
こんな風になってる。で、出力する答えは7になってる。
で、図とにらめっこすると、頂点1からすべての頂点に伸ばせばsum(頂点番号i+1)で表せそう!
ちゃんと難易度どおりの問題に言い換えれました。では実装してみましょう。
C++の例

#include<iostream>
using namespace std;
int main(){
  int N, ans=0;
  cin >> N;
  for(int i=2; i<=N; i++){//全部頂点1につなげるからスタートは2!
    ans += i+1;
  }
  cout << ans << endl;
}

Pythonの例

N = int(input())
L = [i+1 for i in range(2,N+1)]
print(sum(L))

今回もListに入れてsum(List)をすると楽ですね

Keemun - Multiple Multiple (400)

Mに一番近くなる積は何か?という問題。
ここで重要なのは制約で、Nを見るとN<=18となっている。
これは、競技プログラミングでは頻出のbit全探索を疑うといいことが多い。
bit全探索についてはけんちょんさんの神記事で詳しくまとめられているのでそちらを参考に。 各bitを見て1となっている桁数目を掛け合わせる全探索となる。
C++の例

#include<iostream>
#include<vector>
using namespace std;
int main(){
  long long N, M;//Mがintに収まらない
  cin >> N >> M;
  vector<int> v(N);
  for(int i=0;i<N;i++){
    cin >> v[i];
  }
  long long ans = v[0];//とりあえずv[0]を仮置き
  for(int i=1;i<(1<<N);i++){//必ず1つ以上の積になるので1以上
    long long seki=1;
    for(int j=0;j<N;j++){
      if(i>>j&1){
        seki *= v[j];
      }
    }
    if(abs(M-ans)>abs(M-seki)){//absは絶対値
      ans = seki;
    }
  }
  cout << ans << endl;
}
  

Pythonの例

n,m = map(int,input().split());
l = list(map(int,input().split()))
ans = l[0]#変な数字入れてコーナーケース食らわないため
for i in range(1,2**n):#2のN乗
  sum=1
  for j in range(n):
    if i>>j & 1:#iのjビット目が1の時
      sum*=l[j]
  if abs(m-ans) > abs(m-sum):
    ans=sum
print(ans)

感想

いい感じの難易度でwriterさんすげぇってなった。
運営の方もお疲れ様です。 次のコンテストも楽しみにしてます!