CF 958 E3 - Guard Duty (hard)
問題
問題概要
個の白い点と個の黒い点の座標が与えられるので、完全二部マッチングをつくりたい。マッチングさせた者同士を線分で結ぶ時に、その線分が交差しないような割り当て方を答えよ。
- 2点が同じ位置にある・3点が同じ直線上にのることはない
アイデア
(いきなり)余談だが、このように交差しないマッチングを作ることは必ず出来る。そのようなマッチングとは、線分の長さの合計が最小になるような割り当て方である。仮に、このマッチングに対して交差があるような線分があると仮定する。線分とが交差するとき、これらはとの組に繋ぎ替えれば交差はなくなる。そして、この線分の長さの合計は、三角不等式から前者よりも短くなっていることが分かる。
さて、このようなマッチングをどのように構築するかを考える。上で述べたように、白の点と黒の点が同じ個数なら、必ず題意を満たすマッチングを作ることが可能である。よって、1つのマッチングを構成して、それによって出来る線分に対して、領域が2つに分割される時に両方の領域でまた白の点と黒の点が同じ個数になるような線分を常に選び続ける事ができれば、このマッチングは完成する。
今回は、その領域内で、x座標が最小の位置にある点とどれをマッチングさせるかを考える。この時に、点を基準にして偏角ソートしておき、その順番で点を同じなら+1
、違うなら-1
という風にカウントしていくと、初めはカウンターが0からスタートし、最終的には(領域内には白と黒は同じ個数あり、基準にする点として1つ使っているので)-1でカウンターが止まる。このカウンターが-1になる瞬間に、その点とを結ぶことにすれば、それより上と下の領域が両方ともまた白の点と黒の点が同じ個数になる。
これを繰り返して、全てのマッチングが終了するまで試せば良い。これは全部で回行い、1回の動作の中ではソートをするので、全体としてで解くことが出来る。
実装(C++)
続きを読むAOJ 2720 - Identity Function
問題
Identity Function | Aizu Online Judge
問題概要
1より大きい整数が与えられる。次のような関数を考える:
この時、のについてが成り立つような最小のを求めよ。このようなが存在しない時は、-1
を出力せよ。
アイデア
まず、考察したこととしては、が素数の時は、フェルマーの小定理からであることがわかるので素数の時は1が答えになると思った。ただ、素数で無いときにも答えが1になることはあるようでこのような条件を満たす数にはカーマイケル数という名前がついているらしい。
は漸化式の形になっているが、これは帰納的にであることが示せる。
を素数として、のとき、 となることはない。こうなるということは、と書けるということだが、とくくると、この数はしか素因数を持たないはずなのに、括弧内の数はどのようにを選んだとしてもの倍数になることはないからである。
つまり、これ以降で考えるべきとしてはのように、各素因数が1つのみである素数の積の形をしている。
さて、が成り立つためには、各素数でもが成り立っているはずである。さらに、これはのについて成り立っているので(とが互いに素なときでも成立しなければならない)、指数の肩に注目するとと言い換える事ができる。
これがのについて成り立っていて欲しい、ということはLCMを考えてで割り切れて欲しいということになる。よって、この問題はを満たす最小のを見つける、と言う問題になった。
まず、とが互いに素でないならこのようなは存在しない。そして互いに素である場合には、このはオイラー関数の約数である(!?)ので、約数を列挙して順番に試せば良い。
とあるが、なんで約数しかみなくていいんだ...ってなったが、もう一度求めたいものをみてみると、この求めたいというのはまさにカーマイケルのλ関数によって与えられるものであり、それがオイラー関数の約数であることは定義より明らかである(オイラー関数は単純に掛け算しているところで、カーマイケルのλ関数はLCMを取っているので)(参考)。
ただ、今回はNについてのみ成り立ってくれればいいので、やはり約数を小さい方から順にチェックする必要がある。