概要
G の満たす性質をうまく利用しましょう.
問題原案:viral
改題:uni_kakurenbo
解説
任意の 2 非負整数 u,v について u&v=u であることを u⊆v と書きます.
(bit の集合を想像してください.u で立っているビットはすべて v でも立っています.)
また,「A[i]⊆A[j] のとき i→j の辺を張る」とありますが,記号の向きが逆で分かりづらいので「A[i]⊆A[j] のとき i←j の辺を張る」とします.このとき入次数が 0 となる頂点の個数を数えます.
また,「任意の 3 非負整数 u,v,w について『(u⊆v かつ v⊆w) ならば u⊆w』」であることは容易にわかります.(これを形式的に「推移律が満たされている」とも言います.)
また,「任意の相異なる 2 非負整数 u,v について『u⊆v ならば u⊆v ではない』」ことも当然成り立ちます.(これを形式的に「反対称律が満たされている」ともいいます.)
以上のことを踏まえると,A は distinct な (相異なる) ので,グラフ G は 有向非循環 (DAG) になります.(これを形式的に「⊆ が非負整数全体の集合において半順序 (partial order) である」ともいいます.)
つまりトポロジカルソートしたときの末尾となる頂点の個数が分かればいいです.
問題文通りに辺を張ると O(N2) 本になって間に合いません.
なので「⊆ が非負整数全体の集合上で推移律を見たす」ことを利用して辺の本数を削減します.
具体的には,A<220<2×106 の制約を利用します.
新たにグラフ G′ を考えます.G′ には頂点 0,1,2,…,220−1 の 220 個の頂点があります.
各頂点について,「それぞれの頂点を表す非負整数から任意の 1 ビットを下げた頂点へ辺を張る」ことを行います.
d=bit_length(A) とします.(この問題では d≤20)
より形式的には,頂点 i からは,頂点 i&20~,i&21~,i&22~,…,i&2d~ (ただし自分以外) の O(d) 個の頂点へ辺が張られます.
- 任意の非負整数 u に対して u~ は u の bitwise NOT.
このようにすると,⊆ は推移律を満たすので,「任意の 2 非負整数 u,v について『u⊆v ならば G′ 上で [u←v]-path が存在する』」ということになります.
あとは G′ 上で DP を行えばよいです.(G′ ももちろん DAG になります.)
- DP[x]:=(x⊊A[i] を満たすような 1≤i≤N なる整数 i が存在する.[True/False])
- 初期状態:DP[x]=False(0≤x≤maxA)
- 遷移:DP[y]=G′上で[y←x]-pathが存在する⋁(DP[x]∨(x∈A かどうか [True/False]))
詳しくは実装例も参照してください.
たとえば,d=3 のときの G′ は次のようになります:
解説:uni_kakurenbo
実装例