CODE FESTIVALの予選AがAtCoderでありました。

まぁ、久々にプロコンやるかって感じで登録して挑んだんですけど散々でした。

問題はこちら

私の提出したコードはこんな感じ

ちなみに言語は大体なんでもいけます。

わたしはC++で挑みました。

一人反省会やりますけど、850位だった人のやつなんでかなりレベル低いです。

プロコン始めたての人にはためになるかも

 

・A問題

私が書いたのは、charの変数をひとつ持って前から読んでいくスタイルだったですけど、後から考えたら、stringのメンバを使えばスタイリッシュに書けるな

string s;
 cin >> s;
 s = s.substr(0, 4);
 if (s == "YAKI")cout << "Yes" << endl;
 else cout << "No" << endl;

こんな感じ。

最近までCしかやってなかったからstringとか慣れてなかった。

strcmpじゃなくて大丈夫?とか思ってたww

 

・B問題

何列目のスイッチを押そうと一緒。

ようは縦のボタンをいくつと、横のボタンをいくつ押したかが重要。

縦の押した数をn、横の押したか数をmとすると

nNが縦の黒くなる場所、mMが横の黒くなる場所。

ただし、その被った部分(個数はnm)は白くなるので、

正味黒で残るのはnN + mM - 2nm。

これがKになるかを0 <= n <= M、0 <= m <= Nの全ての(n,m)に対して確認すればOK

bool flag = false;

for (n = 0; n <= M; n++)
  for (m = 0; m <= N; m++)
   if (n*N + m*M - 2*n*m == K)
    flag = true;
 if (flag)cout << "Yes" << endl;
 else cout << "No" << endl;

こんな感じ。

これはたぶんこれが一番思いつきやすくて簡単に書けると思う。

 

・C問題

A内の字の並びは重要じゃないので、

 int flag[26];

 for (i = 0; i < 26; i++)flag[i] = 0;

 T = H*W;
 for (i = 0; i < T; i++) {
  int x;
  cin >> A;
  x = (int)(A - 'a');
  flag[x]++;
 }

とりあえず、こんな感じで入ってる文字の個数を調べる。

んで、回文になればいいので、基本的にflagの値が全部4の倍数になってればOK

ただ、HやWが奇数なら全部が4の倍数じゃなくてもいける。

for (i = 0; i < 26; i++) {
  count1 += flag[i] % 4;
  count2 += flag[i] % 2;
 }
これで定義したcount1、2が基本的に0になればよいが、HやWの偶奇によってそれがどう変化するかを考えればいい。

count1はHが奇数ならW、Wが奇数ならHまでの大きさが許される。

ただ、どちらも奇数でも、H+W-1まで。

一方、count2はどちらも奇数で初めて1までの大きさが許される。

これをコードにして、

int p1 = 0, p2 = 0;
 if (H % 2 != 0)  p1 += W;
 if (W % 2 != 0)  p1 += H;
 if (!(H % 2 == 0 || W % 2 == 0)) { p1 -= 1; p2 = 1; }
 if (count1 <= p1&&count2 <= p2)cout << "Yes" << endl;
 else cout << "No" << endl;

D問題以降は全然解けませんでした。

また、やってアップしようかな

では(。・ω・)ノ゙

 

余談

HとWがどちらも奇数という条件は本能的に書いたら

H % 2 != 0 && W % 2 != 0か

H % 2 == 1 && W % 2 == 1

一方、上のコードに使った条件は

!(H % 2 == 0 || W % 2 == 0)

私の好きなド・モルガンの法則です。

 

それと、今回のコンテストでレートが800越えしました。

まだまだ、頑張ります。