2020年3月16日月曜日

CodeChef Match Challenge 2020 - Inverse of a Function

まずは与えられた数列の美しさを求める方法を考える。数列(ai)(a_i)ii桁目が11の数がd(i)d(i)個含まれているとき、d(i)d(i)個から奇数個選べば残りの数をどう選んでもxorのii桁目が11になる。つまり、ii桁目だけに限ってxorの総和を取ると、d(i)>0d(i) > 0なら2i2^i

2Nd(i)((d(i)1)+(d(i)3)+...)=2Nd(i)2d(i)1=2N1 \begin{aligned} & 2^{N-d(i)} \biggl( \binom{d(i)}{1} + \binom{d(i)}{3} + ... \biggr) \\ = & 2^{N-d(i)} 2^{d(i)-1} \\ = & 2^{N-1} \end{aligned}

個足されることになる。すなわち、ii桁目が立っている数が(ai)(a_i)の中に1つでもあれば、ii桁目の総和は2N12i2^{N-1} 2^iであり、ひとつもなければ00である。したがって、全体の総和はbitwise orを使って

2N1i=1Nai 2^{N-1} \bigvee_{i=1}^{N}a_i

と表すことができる。これが(ai)(a_i)の美しさである。

次にF(N,B):=F(N, B) := 長さNNで美しさBBの数列の数、を求める方法を考える。上の式を見ると、BBが与えられたときにB/2N1B/2^{N-1}の立っているビットを考えればよいことがわかる。つまり、B/2N1B/2^{N-1}ii桁目が11なら、NN個の数のうちの少なくとも11つの数のii桁目が11であればよく、ii桁目に限定したNN個の数の選び方は2N12^N-1通りとなる。いっぽう、B/2N1B/2^{N-1}ii桁目が00なら、NN個の数の対応するii桁目はすべて00でなければならないので、選び方は11通りである。したがって、整数xxの立っているビットの総数をc(x)c(x)で表すとき、

F(N,B)={(2N1)c(B/2N1)(B2N1で割り切れる)0(それ以外) F(N, B) = \begin{cases} (2^N-1)^{c(B/2^{N-1})} & \qquad (Bが2^{N-1}で割り切れる)\\ 0 & \qquad (それ以外) \end{cases}

と書ける。

さて、解くべき問題はF(N,B)Xmod  MF(N, B) \equiv X \mod Mを満たす最小のBBを求めるというものだった。上の式を見ると、(2N1)kXmod  M(2^N-1)^k \equiv X \mod Mを満たす最小のk0k \ge 0が求まれば、kk個の11を並べてN1N-1回左シフトしたものが求める最小のBBということになる。これで離散対数問題に帰着できた。

ただし、上の式からわかるように、N2N \ge 2の時は美しさ11の数列がないので、X=0X=0に対しては常に11が答えということになる。(もちろんM=0M=0なら00)。