裏紙

ほぼ競プロ、たまに日記

CF 958 E3 - Guard Duty (hard)

問題

Problem - E3 - Codeforces

問題概要

N個の白い点とN個の黒い点の座標が与えられるので、完全二部マッチングをつくりたい。マッチングさせた者同士を線分で結ぶ時に、その線分が交差しないような割り当て方を答えよ。

  •  1 \le N \le 10000
  •  |x|,|y| \le 10000
  • 2点が同じ位置にある・3点が同じ直線上にのることはない

イデア

(いきなり)余談だが、このように交差しないマッチングを作ることは必ず出来る。そのようなマッチングとは、線分の長さの合計が最小になるような割り当て方である。仮に、このマッチングに対して交差があるような線分があると仮定する。線分B_0 W_1B_1 W_0が交差するとき、これらはB_0 W_0B_1 W_1の組に繋ぎ替えれば交差はなくなる。そして、この線分の長さの合計は、三角不等式から前者よりも短くなっていることが分かる。

さて、このようなマッチングをどのように構築するかを考える。上で述べたように、白の点と黒の点が同じ個数なら、必ず題意を満たすマッチングを作ることが可能である。よって、1つのマッチングを構成して、それによって出来る線分に対して、領域が2つに分割される時に両方の領域でまた白の点と黒の点が同じ個数になるような線分を常に選び続ける事ができれば、このマッチングは完成する。

今回は、その領域内で、x座標が最小の位置にある点bとどれをマッチングさせるかを考える。この時に、点bを基準にして偏角ソートしておき、その順番で点bを同じなら+1、違うなら-1という風にカウントしていくと、初めはカウンターが0からスタートし、最終的には(領域内には白と黒は同じ個数あり、基準にする点として1つ使っているので)-1でカウンターが止まる。このカウンターが-1になる瞬間に、その点とbを結ぶことにすれば、それより上と下の領域が両方ともまた白の点と黒の点が同じ個数になる。

これを繰り返して、全てのマッチングが終了するまで試せば良い。これは全部でN回行い、1回の動作の中ではソートをするので、全体としてO(N^2 log N)で解くことが出来る。

実装(C++)

続きを読む

AOJ 2720 - Identity Function

問題

Identity Function | Aizu Online Judge

問題概要

1より大きい整数Nが与えられる。次のような関数を考える:

  •  f(a) = a^N \ mod  \ N
  •  F_1 (a) = f(a)
  •  F_{k+1} (a) = F_{k} (f(a)) \ (k = 1,2,3, \ldots)

この時、1 \le a \le N-1aについてF_{k} (a) = aが成り立つような最小のkを求めよ。このようなkが存在しない時は、-1を出力せよ。

  •  2 \le N \le 10^9

イデア

まず、考察したこととしては、N素数の時は、フェルマーの小定理からf(a) = aであることがわかるので素数の時は1が答えになると思った。ただ、素数で無いときにも答えが1になることはあるようでこのような条件を満たす数にはカーマイケル数という名前がついているらしい。

F_kは漸化式の形になっているが、これは帰納的にF_k (a) = a^{N^k}であることが示せる。

m素数として、N = p^2 N'のとき、p^{N^k} \equiv p (mod \ N) となることはない。こうなるということは、p^{N^k} = Nx + pと書けるということだが、Nx + p = p(pxN' +1)とくくると、この数はpしか素因数を持たないはずなのに、括弧内の数はどのようにxを選んだとしてもpの倍数になることはないからである。

つまり、これ以降で考えるべきNとしてはN = p_1 p_2 \ldots p_mのように、各素因数が1つのみである素数の積の形をしている。

さて、a^{N^k} \equiv a (mod \ N)が成り立つためには、各素数p_iでもa^{N^k} \equiv a (mod \ p_i)が成り立っているはずである。さらに、これは1 \le a \le N-1aについて成り立っているので(ap_iが互いに素なときでも成立しなければならない)、指数の肩に注目するとN^k - 1 \equiv 0 (mod \ p_i - 1)と言い換える事ができる。

これが 1 \le i \le miについて成り立っていて欲しい、ということはLCMを考えてL = lcm(p_1 -1 , p_2 -1 , \ldots , p_m -1)で割り切れて欲しいということになる。よって、この問題はN^k \equiv 1 (mod \ L)を満たす最小のkを見つける、と言う問題になった。

まず、NLが互いに素でないならこのようなkは存在しない。そして互いに素である場合には、このkオイラー関数 \phi (L)の約数である(!?)ので、約数を列挙して順番に試せば良い。

とあるが、なんで約数しかみなくていいんだ...ってなったが、もう一度求めたいものをみてみると、この求めたいkというのはまさにカーマイケルのλ関数によって与えられるものであり、それがオイラー関数の約数であることは定義より明らかである(オイラー関数は単純に掛け算しているところで、カーマイケルのλ関数はLCMを取っているので)(参考)。

ただ、今回はNについてのみ成り立ってくれればいいので、やはり約数を小さい方から順にチェックする必要がある。

実装(C++)

続きを読む