Official

M - グループ分け / Grouping Editorial by kyopro_friends


\(1,\ldots,N\) の部分集合を単に添字の集合として表すことにします。つまり、「人 \(1,2,3\) からなる集合」のことを単に \(\{1,2,3\}\) と書いたり表現したりします。

予め \(\{1,\ldots,N\}\) の全ての部分集合 \(S\) に対して、「集合 \(S\)\(1\) つのグループにして条件を満たすか?」を調べておきます。これは、愚直に条件を確認することで集合 \(1\) つあたり \(O(N+M)\) でできるため、この処理は全体で \(O(N^2 2^N)\) 時間でできます。
関数 \(f_1\) を、\(\{1,\ldots,N\}\) の部分集合から整数への関数であって、\(S\)\(1\) つのグループにして条件を満たすならば \(1\)、満たさないならば \(0\) と定めます。

次に「\(S\)\(2\) つのグループにして条件を満たすようにできるか?」を考えてみます。このことは、「ある \(X,Y\) が存在して、\(X\cap Y=\emptyset\) かつ \(X\cup Y=S\) かつ \(f_1(X)=f_1(Y)=1\) となるか?」と同値です。
ところで、ある人が複数のグループに属してもよいとしても答えは変化しません。よって \(1\) 番目の条件は無視することができ、考えるべきは「ある \(X,Y\) が存在して、\(X\cup Y=S\) かつ \(f_1(X)=f_1(Y)=1\) となるか?」となります。
\(f_1\) が 01 値関数であることから、これは「\(\sum_{X\cup Y=S}f_1(X)f_1(Y)\neq 0\) か?」と同値です。ここで、\(f_1\) が与えられたとき全ての \(S\) に対して \(\sum_{X\cup Y=S}f_1(X)f_1(Y)\) を求めることは、高速ゼータ変換を用いた畳み込みにより \(O(N 2^N)\) 時間でできます。(後述)
関数 \(f_2\) を、\(\{1,\ldots,N\}\) の部分集合から整数への関数であって、\(S\)\(2\) つのグループにして条件を満たすならば \(1\)、満たさないならば \(0\) と定めます。

さらに「\(S\)\(3\) つのグループにして条件を満たすようにできるか?」は「\(\sum_{X\cup Y=S}f_1(X)f_2(Y)\neq 0\) か?」と同値なので、同様に \(f_1,f_2\) が与えられたとき全ての \(S\) に対してを \(O(N 2^N)\) 時間で計算できます。

以上を繰り返すことで同様に、\(4\) つのグループ、\(5\) つのグループ、……という判定問題を順次 \(O(N 2^N)\) の追加の計算量で求めることができます。求める答えは明らかに \(N\) 以下であることから、この繰り返しは高々 \(O(N)\) 回行えば良く、全体で \(O(N^2 2^N)\) 時間でこの問題を解くことができます。

高速ゼータ変換を用いた畳み込み

まずは次のような問題を考えてみます。

問題:\(f,g\) が与えられるので、\(h(n)=\sum_{\max(x,y)=n}f(x)g(y)\) を全ての \(n\leq N\) で求めよ

愚直に計算すると \(h(n)\) を求めるのに \(O(n)\) 時間かかるため、全体では \(O(N^2)\) 時間かかります。しかし、累積和を用いた次の手法でより高速に計算することができます。

\(h\) の累積和を \(H(m)=\sum_{n\leq m}h(n)\) とします。\(F,G\) についても同様に \(f,g\) の累積和として定めます。このとき \(H(n)=\sum_{\max(x,y)\leq n}f(x)g(y)=F(n)G(n)\) となり、\(H\)\(F,G\) から \(O(N)\) 時間で求めることができます。\(f,g\) から \(F,G\) を求めることと、\(H\) から \(h\) を求めることは \(O(N)\) 時間でできるため、全体で \(O(N)\) 時間で \(h\) を求めることができました。

図

元の問題に戻ります。考えているのは次の問題でした。

問題:\(f,g\) が与えられるので、\(h(S)=\sum_{X\cup Y=S}f(S)g(Y)\) を全ての \(S \subset \{1,2,\ldots,N\}\) で求めよ。

先程の問題と全く同様に累積和を考えます。\(H(T)=\sum_{S\subset T}h(S)\) とします。\(F,G\) も同様に定めます。このとき \(H(S)=\sum_{X\cup Y \subset S}f(X)g(Y)=F(S)G(S)\) となり、\(H\)\(F,G\) から \(O(2^N)\) 時間で求めることができます。よって あとは \(f,g\) から \(F,G\) を求めることと、\(H\) から \(h\) を求めることが高速にできればよいです。

\(f\) から \(F\) を求める操作は多次元累積和にほかならないので、この操作と逆操作は \(O(N 2^N)\) 時間でできます。

(図:\(N=2\) の例)
図

よって、全体で \(O(N 2^N)\) 時間で \(h\) を求めることができました。

posted:
last update: