不定期プログラミング覚え書き

青コーダーと黄コーダーの間を彷徨う社会人プロコン勢が余力のあるときに復習した内容をまとめるブログ

SRM536

結果報告

試しに作った。多分長続きはしないけど前回SRMの報告でも書いとく。

Level ProblemName Status Point
Easy MergersDivOne PassedSystemTest 195.38
Medium RollingDiceDivOne ChallengeSucceeded 0.00
Hard BinaryPolynomialDivOne Opened 0.00

Challenge Phaseで撃墜2成功2失敗で+50点だった。

Easy MergersDivOne

問題

初期状態では複数お店があり、それらの収入が数列として与えられる。
このお店のうちm店を合併させると、新たに出来るお店の収入は元のお店の収入の平均値であることが知られている。
店舗の合併を繰り返し、最終的には1店舗にしたい。最後に残った店舗の収入の最大値を答えよ。

考えたこと

最初の10分強くらい、数列の順番入れ替え不可&一度に合併出来る店舗が2店であると勘違いしてdpを書いてた。
書いてから最後のテストケースが通らないことに気づいたので、取り敢えず最後のテストケースについて考察する。。
入力{10, -10, 100, -100, 1000, -1000}に対して491.25を返したいのだから、
1000の与える影響が大きくなれば良い。逆に、-1000の与える影響は極力小さくしたい。
何となく、小さい順に二個ずつ合併させて言ったら良いんじゃね?と思う。
仮に三店舗あった場合も、その収入を小さい順に r_1,r_2,r_3とした時、
三店舗一気にまとめた \frac{r_1+r_2+r_3}{3}よりは、二店舗ずつ小さい方からまとめた\frac{\frac{r_1+r_2}{2}+r_3}{2}の方が、r_3の寄与が大きくてお得そう。
ガリガリと数式を弄ったら一般的に \frac{r_1+r_2+r_3}{3}\leq \frac{\frac{r_1+r_2}{2}+r_3}{2}と言うことはすぐ示せた。
というわけでこの方針で書いた。コードがさくっと書ける分最初の10分ロスが痛かった。

コード
  double findMaximum(vector <int> revenues) {
    sort( revenues.begin(), revenues.end() );
    int size = revenues.size();
    double ans = revenues[0];
    for( int i = 1 ; i < size; i++ ){
      ans+=revenues[i];
      ans/=2;
    }
    return ans;
  }

計算量はO(n)。nが最大50なので余裕。

後付け考察

なんか書くかも。

Medium RollingDiceDiveOne

問題

色々な数の面をもつダイスがある。ダイスの面の数が数列\{D_i\}として与えられi番目のダイスは1以上D_i以下の数字を等確率で出す。
ダイスをすべて振った時に出た目の総和で、もっとも高確率で出現するものを答えよ。複数ある場合はその中でも最小の値を返せ。

考えたこと(嘘解法)

ダイス目の期待値を全部足してみたらどうかと考えてみる。何となく期待値が一番表現パターン多そうだし。
最小値を返すためには、例えば入力が{10}の場合だったら1を返したいし、{1,1,10}とかが入力の場合は3を返したい。
これは1の個数を調べておいて、1以外の値が1つ以下の時に1面ダイスの個数+1でも返しとけば良いんではないか。
(蛇足だがこれも微妙に嘘。1以外の値が0の時は1面ダイスの個数を返すべきだった。それを修正してもなお嘘解法だけど)
少なくてもテストケースの小さいものについてはすべてこの方針で行けそうだ。
書いてみたら最後のケースまで通ってやがる…よろしいならば記念submitだ。

Challenge Phase前にガシガシ紙に書いていたら、この場合、入力{2,5}の場合に出力4を返すが、正しい答えは3であるという事に気付く。
撃墜争いになると思ったので、ぱっとみて似た方針っぽいコード4つに対してこの入力でチャレンジ。
結果、2撃墜2失敗だった。もうちょっとコードをしっかり見たほうが良かったんだろうな。

Hard BinaryPolynomialDivOne

問題

係数が0か1の1変数n次多項式Pの係数が配列\{a_i\}によって渡される。(a_i x^iの係数)
この時、入力kと入力mに対して、与えられた多項式のm乗を2の剰余系で計算した時のx^kの係数に該当する値を返せ。

考えたこと(途中)

例えば多項式Pがax^2+bx+cの時、
その2乗の係数は\{a^2,0,b^2,0,c^2\}=\{a,0,b,0,c\}で、
4乗の係数はa,0,0,0,b,0,0,0,cで…なんか規則性がありそう。
もうちょっと踏み込むと、P^{(2^i)}x^kの係数は、P^{(2^{i-1})}x^{k/2}の係数で決まり、kが奇数なら0しかありえない。
つまり、m=2^Mとかだったら O(\log m)で計算出来る。

……
………
でっていう?
例えばm=2^{m_1}+2^{m_2}+2^{m_3}だったらP^m=P^{m_1}*P^{m_2}*P^{m_3}なわけだが。
これが例えば足し算だったら解けるけど、掛け算だしねえ。