ABC013 C 節制
先日 AtCoder Virtual Contest でやっていたABCのC埋めに出てきて、コンテスト中には解けなかったのでゆっくり解いていたが、満点解法がわからなかった&&時間がかかったので書く。
C: 節制 - AtCoder Beginner Contest 013 | AtCoder
問題概要
N日間の食事を次の3つから選ぶ。
・普通の食事 ( 出費A円、満腹度 +B )
・質素な食事 ( 出費C円、満腹度 +D )
・食事抜き ( 出費なし、満腹度 -E )
最初の満腹度がHで、一度も満腹度が0以下にならないとき、最低何円でN日間乗り切れるか。
制約
部分点
10点…… を満たすテストケース
40点…… を満たすテストケース
100点…… を満たすテストケース
101点…… すべてのテストケース
部分点解法その1
の解法。問題を見た時にまずこれが浮かんだ。
日にちと満足度が決まればそのときの最小の食費は一意に定まるので、
dp[i][j]:=i日目に満足度がjであるときにかかる最小の食費
という配列をもつDPで解ける。
満足度の上限はH+NBより
計算量は つまり 。
部分点解法その2
の解法。DPが思いついたあと、100点解法では満足度の上限がないため、満足度を使わずに食費が一意に定まるものは他にないかと考えて、「それぞれの食事をした回数が決まれば、満足度も食費も求めることができる!」と気づいた。
普通の食事の日数と質素な食事の日数が決まれば、食事抜きの日は「 n - (普通の食事の日数) - (質素な食事の日数) 」に決まるから、計算量は 。
Submission #1111965 - AtCoder Beginner Contest 013 | AtCoder
普通の食事の日数をi日、質素な食事の日数をj日とすると、食事を抜く日数はn-i-j日である。
このとき、n日目の満足度は「 」であるから、これが0より大きければ満足度が一度も0以下になることがないような食事の順番が存在する*1。よって、このときの合計の食費「 」が今までの暫定の最小の食費よりも小さければ暫定値を更新する。
満点解法
の解法。思いつかなかったので解説を見たら頭が良かった(それはそう)。
制約より、満腹度が大きくなるほど合計の食費も大きくなるので、合計の食費をできるだけ小さくするには満腹度が(一度も0以下にならないという制約を満たしつつ)できるだけ小さくなるようにすればいい。
つまり、普通の食事の日数をi日、質素な食事の日数をj日、食事を抜く日数はn-i-j日としたとき、 を満たすようなiとjのうち、iとjが最小になるものを考える。
2変数であるから、計算しやすいように片方の変数iを固定して考える*2。
iを固定したとき
となる最小の整数jは で求まる。
これを についてそれぞれ調べるので、全体の計算量は 。
Submission #1112041 - AtCoder Beginner Contest 013 | AtCoder
普通の食事の日数がi日のとき、質素な食事の日数が0日かそうでないかで場合分けをする*3。
のときは質素な食事の日数が0日で良いため、合計の食費は となる。
のときは、最小となるjを求めて、 のとき(普通の食事の日数と質素な食事の日数の合計がn日以下のとき)は、合計の食費は となる。 合計がn日より大きい場合は、なかったことにする。
感想
ABCのCなのに難しい問題が多くてつらい(人権がない)
AGC005 B Minimum Sum
昨日解いていて、解説を見ても理解するのに手こずったので、考え方を書いてみる(一応この問題について書いてるブログはあったけど、解法が違ったので、自分用に)。
B: Minimum Sum - AtCoder Grand Contest 005 | AtCoder
TLE解法
自力で思いついたのは全区間の最小値を順番に足していく の解法。
調べる区間の幅をだんだん大きくしていくという考え方。
Submission #1101992 - AtCoder Grand Contest 005 | AtCoder
ansの初期値に代入している は、隣り合う1項の最小値(つまりその項自身)の合計値。数列には から までの数がそれぞれ1回ずつ出てきているので、等差数列の和と考えて計算する。
repの中では、隣り合う 項の最小値を計算してansに足していく。
区間(部分数列)でいうと
{} {} … {}
{} {} … {}
…
{} {}
{}
の最小値を順番に求めている。
setを使った解法
の解法は「最小値が となる区間がいくつあるかを計算し、その区間数と の積の合計を求める」。
が最小値となる区間は、数列の より前の部分で に一番近いところにある よりも小さな値との距離、数列の より後ろの部分で に一番近いところにある よりも小さな値との距離がわかれば求めることができる。
たとえば、{5, 4, 9, 2, 1, 8, 6, 7, 3}という数列の6が最小値となる区間を考える。
6が最小値になる区間は6より小さな値が存在しないので、もとの数列の6より小さい値にだけ色をつけると
{5, 4, 9, 2, 1, 8, 6, 7, 3}
となり、6より小さな値(赤色の数字)が存在しないような区間(部分数列)は{8,6}{8,6,7}{6}{6,7}の4つとなる。
ここで、6が最小値となる区間の左端は、はじめの数列の「6より左にあって6より小さな一番6に近い値(=1)」よりも右で、6よりも右ではない数字になっていることがわかるので、6が最小値となる区間の左端は8,6のどちらかであり、この8,6という左端の候補の数(=2)は「6より左にあって6より小さな一番6に近い値(=1)」と6との距離である。
同様に、6が最小値となる区間の右端は6,7のどちらかであり、右端の候補の数(=2)は「6より右にあって一番6に近い6より小さな値(=3)」と6との距離である。
そして、6が最小値となる区間の数は(左端の候補の数)*(右端の候補の数)より2*2=4個と求めることができる。
今見ている数字 が最小値となる区間の数を求めるためには、 の左右それぞれで、より小さく に一番近い数との距離が必要になる。 よって、要素を自動的にsortしてくれるsetに、 より小さな値の添字を入れておき、 の添字iに一番近い数をlower_boundを使って高速に調べればよい。
が最小値となる区間を調べる際に必要な情報は「 よりも小さな値がどこにあるのか」なので、できるだけ小さな 、つまり1から順番に調べていくと、区間数を調べた後にsetにをそのまま入れることができるので、効率よく求めることができる。
setの要素の挿入に 、set内のlower_boundに かかるので、それぞれに対して行っても 。
Submission #1102173 - AtCoder Grand Contest 005 | AtCoder
入力を配列aで受け取り、配列orderには、区間数を調べる の順番になるように、 の添字iを格納する。つまり、a[order[0]]=1, a[order[1]]=2, … , a[order[N-1]]=Nとなるように格納する。
はじめにsetに入れた-1とNは番兵の役割をする。の前に より小さな値が存在しないときは-1が返され、の後ろに より小さな値が存在しないときはNが返される。
その他の解法
pekempeyさんがUnion-Findを使った解法を解説しています。
AtCoder Grand Contest 005: B. Minimum Sum - pekempeyのブログ
また、standingsで他の人のソースコードを見てみると、stackを使った解法などもあるようです(私にはよくわからなかったのですが……)。
最後に
この問題が400点なんて嘘ですよね?(500はありそうだと思った)
エクセルでの乱数発生のメモ
この春休みは計算力を上げることを目標として頑張っているので、さまざまなことに取り組んでいる。その一環として使うプリントを作成した。その際の「1から100までの整数をランダムに(重複なしで)表示させる方法」をメモしておく。難しくはなく、簡単にできるので大量にプリントを作ることができた。
以下その方法。
①エクセルを起動させる
ここは気合いでなんとかなる。
②A1に「=RAND()」を入力する
RAND関数は0以上1未満の小数の乱数を作る関数である。
③A100までコピーする
これで、0以上1未満の小数の乱数がA1からA100まで100個作成できた。
④B1に「=RANK(A1,$A$1:$A$100,0)」を入力
RANK関数はRANK(数値,参照範囲,順序)で入力すると、[数値]が[参照範囲]の中で[順序]で何番目かを返す。[順序]は0か1を入力でき、0ならば降順(大きい数字の方が順位が高い)、1ならば昇順(小さい数字の方が順位が高い)である。
あとでこの式をコピーするので、[数値]は相対参照、[参照範囲]は絶対参照(「$」をつける)にしておく。
⑤B100までコピーする
これで、A1からA100に書いてある数字の順位がB1からB100に表示される。乱数の順番を表示させているので、重複を避けることができる。
証明を書いていたら循環論法になってしまいましたよという話
簡単なはずの証明問題にやたら時間がかかっていたことの弁明をしたいと思います(弁明にはならない)。
今日の夕方に投稿した記事の証明問題の話です。
「aのn乗がpの倍数であること」と「aがpの倍数であること」は同値である - 足跡-sokuseki-
これの⑵の証明の際に、対偶を帰納法ではなくそのまま証明できないかと奮闘していました。
以下がその証明部分です。
『 が の倍数 が の倍数 』を示すために、その対偶である
『 が の倍数でない が の倍数でない 』を示すことにします。
を正の整数として、 とおきます。
ただし、については とします。
このとき
となりますが、ここで二項定理を使います。二項定理は
というものです。これを利用すると
となります。ここで、 のとき は の倍数であり、
の倍数を足し合わせたものである も
の倍数になります。
また、 より、 は の倍数ではないので、
もの倍数ではありません。
よって、はの倍数ではありません。
以上より、対偶を示すことができたので、十分条件が成り立つことがわかりました。
色を変えたところが循環論法になっています。
これをどうしようか……と悩んでいて時間が経ってしまったわけです。
なお、当該記事では帰納法を使っていますが、これは、どうしてもうまくいかなくて、数学の先生に
「『 が の倍数でない が の倍数でない』はどうやって示せばいいですか」
と質問したところ、帰納法を使えばいいよというアドバイスをいただいたので、帰納法でやってみた次第です。
私が自力で思いついたわけではないです。はい。
(帰納法ということを教えてもらっただけで中身の証明は自分で考えたのですが、そのせいで無駄に長い証明になってしまいました……)
なお、さきほど短いver.を追記しました。
以上、弁明にもならない弁解でした。
「aのn乗がpの倍数であること」と「aがpの倍数であること」は同値である
根号のついた様々な数が無理数であることを示すのが最近の趣味です。
その証明に使う補題(のようなもの)を証明したいと思います。
証明内容はタイトルにも書いた通り、
『 が正の整数、 が素数のとき、
が の倍数 が の倍数 』
です。必要条件と十分条件に分けて証明していきたいと思います。
⑴『 が の倍数 が の倍数 』を示す
を整数として、 とおきます。このとき
は の倍数なので、 が の倍数であることがわかります。
よって必要条件は示すことができました。
⑵『 が の倍数 が の倍数 』を示す
これを直接証明することは難しいので、対偶を示すことにします。
『 が の倍数 が の倍数 』の対偶は
『 が の倍数でない が の倍数でない 』……(*) です。
なので、(*)を数学的帰納法を使って示します。
(i) まずは のとき
「 が の倍数でないならば が の倍数でない 」は自明なので(*)は成り立ちます。
(ii) 次に、 のときに(*)が成り立つと仮定します。
このとき仮定より、「 が の倍数でないならば、 が の倍数でない」といえます。
またこのとき、
「 の倍数でない数に、 の倍数でない数をかけても の倍数にはならない 」……(A)
ということがいえるならば、
の倍数でない に、 の倍数でない をかけた も の倍数ではありません。
よって(A)さえ示すことができれば、 のときも(*)が成り立つといえます。
ここで(A)を示すために、 の倍数でない2数の積を で割ったあまりについて考えます。
(ここでは合同式を使って、整数 を整数 で割ったあまりと、整数 を整数 で割ったあまりが等しいとき
「 ( mod ) 」と表すことにします。 )
整数 を用いて、 の倍数でない2数を
、 (ただし、 かつ )
とします。
この2数の積を で割ったあまりは
( mod )
と表せます。
ここで、「 ( mod ) 」と仮定すると、
は の倍数であり、 は素数なので、
と の少なくとも片方が「 0 または の倍数」である必要があります。
しかし、 より、
と の両方ともが 0 でも の倍数でもないので、これは矛盾します。
よって 「 ( mod ) 」という仮定が間違っていることがわかります。
以上より ( mod ) となります。
よって、 ( mod ) となり、
の倍数でない2数の積は の倍数でないことが示せました。(A)の証明はこれで終了です。
これで、
(i) のとき(*)が成り立つ
(ii) のときに(*)が成り立つならば、 のときに(*)が成り立つ
を示すことができたので、数学的帰納法より(*)を証明することができました。
対偶である(*)を証明することができたので、
『 が の倍数 が の倍数 』が成り立つことが証明できたことになります。
よって、必要条件、十分条件ともに成り立つことがわかったので、
『 が正の整数、 が素数のとき、 が の倍数 が の倍数 』
を証明することができました。
ところでこの証明、名前ついてたりするんですかね……。有名な気がするんですが……。
参考サイト
追記
この記事を投稿した後に、@lvbourbakiさんに指摘していただいて気づいたのですが、(A)の証明の部分で合同式を使って式変形をする必要はありませんでした。
ということで、簡潔になった(A)の証明を以下に書きます。
の倍数でない2つの自然数を とします。
ここで、「 が の倍数である 」と仮定すると、 は素数なので、
と の少なくとも片方が「 0 または の倍数」である必要があります。
しかし、 と の両方ともが 0 でも の倍数でもないので、これは矛盾します。
よって 「 が の倍数である 」という仮定が間違っていることがわかります。
以上より は の倍数でないということがいえるので、
の倍数でない2数の積は の倍数でないことが示せました。
じ、自明だ……
ということで随分と短くなりました。
@lvbourbakiさん、どうもありがとうございました。
競技プログラミング2016総括
ということで競技プログラミング1年目のまとめをします。長くて面倒なので箇条書きスタイルでいきます。
4月
- 大学に入学し、学部のガイダンスでRiPProに出会う
- RiPPro主催のC言語講習会に行く
- 競技プログラミングをやってみる
- 「競技プログラミング面白そう!」
- RiPProの活動に行くようになる
- AOJ初AC
5月
6月
- 1年3人でチームを組んでICPC国内予選に出る(1完)
7月
- 大学の期末テストで競プロできない日々が続く
8月
- 夏休みだったので毎日AOJを目標にしてた(できたとは言ってない)
9月
- ACPCに参加(初めてのオンサイトコンテスト&&初めての作問)
- AtCoderで100solved達成!
10月
- KUPCに参加
- AOJで100solved達成!
- AtCoderのレートが1200突破!
11月
- 何してたっけ……?
12月
現在のAC状況(2016/12/30 17:00現在)
AOJ……133solved
(解いてるときと解いてないときの差が激しい)
AOJ-ICPC……47solved
AtCoder……253solved
(ABCのAB埋めが完了したので解ける問題が少なくなって進捗がなくなってきた)
最後に……
来年も競技プログラミング頑張ります!
たくさんのオンサイトコンテストに行けるといいな〜
今までに詠んだ和歌をまとめた
和歌。それは少ない文字数に景色や心情を詠みこむ日本独自の歌。決まった文字数に様々な、時には二通りにも三通りにも読み取れる意味を込める和歌は、とても素晴らしい文化だと思います。
和歌を詠んだ経験は少ないのですが、イベントに関連してTwitterで和歌を募集していた際などに詠んだいろいろな和歌を一度まとめます。
愛と数学の短歌コンテスト
4月に理系彼女botさんが考案、横山明日希さん(数学のお兄さん)が主催して行われたコンテスト。
【愛と数学企画第3弾】
— 横山明日希-数学のお兄さん- (@asunokibou) 2016年4月7日
お待たせしました!愛と数学企画第3弾「愛と数学の短歌コンテスト」開催!
4/30まで!賞品アリ!#愛と数学の短歌コンテスト をつけツイートで応募完了です
詳細→https://t.co/akWtGOWvps pic.twitter.com/qKth7PWEnT
【#愛と数学の短歌コンテスト 優秀賞発表!】
— 横山明日希-数学のお兄さん- (@asunokibou) 2016年5月7日
受賞者は3名!おめでとうございます!1,300件の応募から3つだけに絞るのがすごく悩みましたが、こちらの3作品に決定しました。
賞品は、短歌を書いた扇子をプレゼント!おめでとうございます pic.twitter.com/8aObzZbAg2
短歌も和歌の一種ということで。技法とか何もないのが多いですが。
君以外
— りか (@wk1080id) 2016年4月10日
不適となれば
背理法
解なしなどと
させてたまるか
#愛と数学の短歌コンテスト
将来の 互いを想う 期待値は
— りか (@wk1080id) 2016年4月10日
友達以上 恋人未満
#愛と数学の短歌コンテスト
なんか2番煎じ臭がする…
eとπ 無限に続く 無理数も
— りか (@wk1080id) 2016年4月10日
愛情与へば 整った数
#愛と数学の短歌コンテスト
オイラーの等式「e^iπ=-1」より
i乗を愛情と掛けてみました
君が言う「私、嘘つき」真ならば
— りか (@wk1080id) 2016年4月10日
僕へと告げた 想いは偽(ぎ)なの?#愛と数学の短歌コンテスト
クレタ人のパラドックスみたいなイメージです
思い出の
— りか (@wk1080id) 2016年4月10日
等比級数
求むれば
日々ます気持ち
無限大かな
#愛と数学の短歌コンテスト
愛(i)ふたつ どちらが大きく 見えようと
— りか (@wk1080id) 2016年4月11日
存在しない 優劣順序#愛と数学の短歌コンテスト
虚数は大きさを比較できないというのと2人の愛情の大きさを比較しても意味がないってことをかけてみた
恋心 君は見えぬと 言ふけれど
— りか (@wk1080id) 2016年4月12日
されば係数 1の如しと#愛と数学の短歌コンテスト
2進数 世界に唯一 1と0
— りか (@wk1080id) 2016年4月13日
僕もあの子と 2人でいたい#愛と数学の短歌コンテスト
君以外 きっと誰にも わからない
— りか (@wk1080id) 2016年4月13日
君と2人で 数式会話#愛と数学の短歌コンテスト
2人だけの世界をつくれるのっていいですよね。
逆向きの 愛と愛とで ゼロなれど
— りか (@wk1080id) 2016年4月21日
愛重なれば 実る愛情#愛と数学の短歌コンテスト pic.twitter.com/IANWNNERSa
君と僕
— りか (@wk1080id) 2016年4月28日
GCDの
大きさと
想う気持ちに
相関はない#愛と数学の短歌コンテスト
相手との
— りか (@wk1080id) 2016年4月28日
LCMで
測ろうか
これからつくる
2人の思い出#愛と数学の短歌コンテスト
@mass_sawood
— りか (@wk1080id) 2016年5月1日
虚数軸
線分原点
体積と
ネイピア数と
和集合かな#愛と数学の短歌コンテスト
締め切りすぎちゃってるけど思いついたので投稿
これは@mass_sawood さんのツイートが元ネタ。すべてローマ字にすると "I love U" になります。
君は言う「素数=(は)素敵」
— りか (@wk1080id) 2016年6月7日
因数に ただ一通りの 君と僕のみ
#愛と数学の短歌コンテスト
ロマンティック数学俳句コンテスト
7月から8月にかけて、横山明日希さん(数学のお兄さん)主催で行われたコンテスト。
【ロマンティック数学俳句募集します!】
— 横山明日希-数学のお兄さん- (@asunokibou) 2016年7月21日
数学×ロマンの俳句を募集!819(ハイク)の日に開催される #ロマンティック数学ナイト に合わせ、WEB企画行います!#ロマンティック数学俳句コンテスト をつけて皆様の投稿お待ちしてます! pic.twitter.com/YTXT8dKMeb
【ロマンティック数学俳句結果発表】#ロマンティック数学ナイト こちら3名が優秀賞です!@yu_kashikura @y0k0t0m0 @mitsmath
— 横山明日希-数学のお兄さん- (@asunokibou) 2016年8月19日
おめでとうございます!#ロマンティック数学俳句コンテスト pic.twitter.com/12SZHAQSp7
このコンテストについては、ツイートしてないのですが、スマホのメモに当時考えたものが残っていたので。
関数で 君は一意に 僕とペア
「関数はある数を決めるとそれに対応して一つの数が決まる。関数のように、君と僕が一対一で対応する、っていうニュアンス」という解説まで残っていました(笑)
数学和歌を詠もう
8月末から、横山明日希さん(数学のお兄さん)と狡猾な狐さんが企画して行われたイベント。
【和歌×数学イベント開催決定】
— 横山明日希-数学のお兄さん- (@asunokibou) 2016年8月26日
9/10(土)18時~「数学和歌を詠もう」を開催!
数学の美しさと和歌の美しさ、両側面から分かりやすく解説します!#数学和歌を詠もう
申込はこちら⇒https://t.co/wLVWFqahPm pic.twitter.com/1rmyNkGRI8
イベントまでに詠むことはできなかったのですが、その後行われたツイキャスで詠みました。
【告知:数学×和歌の生配信】
— 狡猾な狐 (@wreck1214) 2016年10月12日
10/16の20時から、#数学和歌を詠もう ツイキャスします!
前回のイベント後に詠まれた数学和歌をピックアップし、和歌、数学、それぞれ観点から解説!数学のお兄さん、キグロさんと+αのメンバーで和歌の世界に入り浸ります!皆さんの数学和歌お待ちしてます pic.twitter.com/NdBMzthyJi
訂正。#数学和歌を詠もう
— りか (@wk1080id) 2016年10月16日
僻事で 楯つく輩 骨すれど
埒あかぬ末 数の拡張
(ひがことで たてつくやから こつすれど らちあかぬすえ すうのかくちょう) https://t.co/pZ4SABTJUT
そしてセルフ解説はこちら。
ピタゴラスは三平方の定理を考えたけど、斜辺の長さがどうしても自然数にならない直角三角形が存在することに気づいた。ピタゴラス教団はその事実をひた隠しにしてバラそうとした人を殺したりしたけど、結局は数を自然数から拡張して新たな数の集合(実数)ができた。#数学和歌を詠もう https://t.co/KyZPcwYckJ
— りか (@wk1080id) 2016年10月16日
そしてこのハッシュタグを使って、その後もいくつかツイートしてます。
素数のみ 因子の積で 数示す
— りか (@wk1080id) 2016年10月27日
分かつ方法 解ただ一つ
#数学和歌を詠もう
— りか (@wk1080id) 2016年11月8日
これはただのネタです(笑)
古今和歌集の日
2016年11月11日の古今和歌集の日を記念して和歌を詠もうという企画(狡猾な狐さん発案)。
収録和歌数が1111首なのと、今年で奏上から1111年目なのとで、今日は #古今和歌集の日 です。詠んで!と言いましたが、好きな和歌を紹介するだけでも、古今和歌集についてちょこっと調べるだけでも構いません。一緒に古今和歌集を楽しみましょう!^ ^
— 狡猾な狐 (@wreck1214) 2016年11月10日
目が覚めて 冷えた空気と 出席数
— りか (@wk1080id) 2016年11月10日
どちらも捨てて 布団を選ぶ
#古今和歌集の日
字余りですが、大学生あるある
遠きまま やうやう寒くなりぬれど
— りか (@wk1080id) 2016年11月10日
近づく二人 妨ぐ小春
#古今和歌集の日
罰ゲーム 二人で端から 食べ始め
— りか (@wk1080id) 2016年11月10日
触れるくちびる 恋の始まり
#古今和歌集の日
11/11なので。
寝て覚めて 海をさまよい 瞠目す
— りか (@wk1080id) 2016年11月10日
我が和歌いみじ 稚拙なりけり
#古今和歌集の日
悦楽す まえから見ても あとからも
— りか (@wk1080id) 2016年11月11日
ふたつ素数の 数で遊ぼう#古今和歌集の日#数学和歌を詠もう
月満ちて 我が灯は 体のかげ
— りか (@wk1080id) 2016年11月11日
いつか虧くとて 学志す
#古今和歌集の日
いろいろ込めてみた(頑張った)
これについてはセルフ解説を以下に。
小さな存在だった私は成長し、師を追い越してしまった。(私を照らしていた灯を目立たなくしてしまったこの満月もいつかは欠けてしまうように)いつか私にも周りの人や後世の人に抜かされる日が来るであろうが、日陰者にはなりたくないので、さらに深く勉強していこうと思った。#古今和歌集の日
— りか (@wk1080id) 2016年11月11日
いくつかツイキャスで紹介もしていただいて、本当にありがとうございました!
最後に
古今和歌集からの良き節目を迎えて、せっかくだから、と今までの分もまとめました。もっと良い和歌を詠めるようになりたいです。