Weitere ähnliche Inhalte
Ähnlich wie K2PC Div1 E 暗号化
Ähnlich wie K2PC Div1 E 暗号化 (20)
K2PC Div1 E 暗号化
- 2. 統計
● First Acceptance
iwiwi(75:11)
● 完答数 / 提出数 = 2 / 45
正答率: 4.4%
● 部分点(500)最初に手に入れた人
みけCAT(59:36)
- 3. 問題
● 長さ10万の数列が与えられる
● その数列の連続した部分列に対して、
Pを素数とする. ハッシュ化する列を {x1,x2,x3,…,xn} とし, 全
ての xiについて, j≦
iかつ xj=xiが成り立つような jの個数をCiと
すると,
(ハッシュ値) = ΣxiCi mod P
● という風にハッシュ値を求めるだけの問題。
- 4. 部分点(20%)
● 数列中の数は全て異なる⇔常にCiは1
●
つまり、
(ハッシュ値) = Σxi mod P
● これは累積和を使えば
前計算O(N)
1つのクエリ処理O(1)
全体としてはO(N+Q)
● すごく簡単。
- 5. 考察
● 部分列の特定の数(aとする)だけに着目すれば、
a1 + a2 + … + a(aが列中に存在する個数)
がハッシュ値に足されている。
● クエリは出力順だけ正しければ、どういう順番に
処理しても構わない。
- 6. クエリ処理のメインアイデア
● もしクエリが(始点,終点)のペアでソートされてたら
(1,2) , (1,5) , (1,7) , (2,1) , (2,2) , …
●
みたいな感じになる。
●
始点が同じやつはまとめて処理できるので嬉しい
– なぜかというと、たとえば
(1,2)の結果がもとまっているとして、
(1,5)の結果はそれの右端を3伸ばしたものであり、
(1,7)の結果はさらに右端を2伸ばしたものだから。
● しかし始点が全て異なる場合やはりクエリ処理全体でO(NQ)か
かってしまう。
- 7. 計算量改善(間違いだらけかも)
● そこで、始点を√n個程度のバケットに分けて、
(始点が含まれるバケットの番号,終点)
のペアでソートすると、以下のことが分かる。
– さっきは右端しか伸びなかったが、今回は左端が伸びたり縮んだり
する可能性がある。
– ↑について、バケット内での1つの要素について、O(√n)回左端が
伸びたり縮んだりする。
– それ以外の部分で、1つのバケットにつき後ろがO(N)回伸びる。前
もO(N)回伸びる。つまり前後が,O(2N√N)回伸びる。
– 全体としてはO(Q・√N+2N√N)=O((Q+2N)√N)
– √(2N)をバケットにすると、O((Q+N)√(2N))になる?。こっちのほうが
はやいらしい
- 8. 補足
● 何の断りも無しに左右端を伸ばしたりするアイデアを説明したけ
ど、イメージとしては尺取法みたいにうにょうにょする感じ
●
ほかには、この解法でやるとき、
– ある数aを取り除くときハッシュ値にa(列中のaの出現数)を引けばよい
– ある数aを追加するときaハッシュ値にa(列中のaの出現数+1)を足せばよい
● ということを補足しておきます。
- 9. なぜかTLEした人たちへ
● 余り取るのとかメチャクチャ遅いので、%の数を
ソースから減らすだけで数秒単位で高速化できま
す。オススメ。
- 10. 罠(にしたかった)
● Pは素数ですが、Pと互いに素じゃない数が含まれている場合、割
り算定義出来ないので、先に逆元求めて色々しようとしている人
は破綻してほしかったけどうまくいくらしいです