Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RedCoderがTypeScriptで競技プログラミングに挑戦して挫折した話

forcia_dev_pr
December 07, 2022
1.2k

 RedCoderがTypeScriptで競技プログラミングに挑戦して挫折した話

Shinjuku.ts#1発表資料

forcia_dev_pr

December 07, 2022
Tweet

Transcript

  1. 自己紹介 • 浦上 真之(Masayuki Urakami) 
 ◦ Twitter: @tempura_cpp 


    • ソフトウェアエンジニア@フォルシア株式会社
 ◦ Webアプリケーション開発(TypeScript, Node.js, React, Next.js, PostgreSQL など)
 • (元)競技プログラマ
 ◦ AtCoder で最高レート 2865 を達成(上位約0.3%)
 2 あとでいい感じの 画像に置き換える

  2. 問題① (Atcoder Beginner Contest 277 B問題) 問題概要 2 文字の文字列がN個与えられるので以下の3つの条件をすべてみたすか
 (≒トランプの手札を表す文字列として適切か)判定せよ。


    • それぞれ文字列の1文字目は H, D, C, S のいずれかである
 • それぞれ文字列の2文字目は A, 2, 3, …, 9, T, J, Q, K のいずれかである
 • 全ての文字列は相異なる
 5
  3. 問題② (競プロ典型90問 055) 問題概要
 N 個の整数 A1, A2, ⋯, AN

    と整数 P, Qが与えられる。
 この中から 5 個を選ぶ方法のうち、これら 5 個の整数の積を P で割ると Q 余るような
 ものが何通りあるか求めよ。
 制約
 • 5 <= N <= 100
 • 0 <= Ai <= 10^9
 • 0 <= Q < P <= 10^9
 実行制限時間
 5 秒
 7
  4. 何がダメ? • 整数を5個掛け算すると、最大で(10^9)^5 = 10^45 
 • JavaScript の MAX_SAFE_INTEGER(=

    2^53 - 1) を大きく上回っているので整数を正確に表 現できないため間違った答えになってしまう 
 • a[i1] * a[i2] % p * a[i3] % p * a[i4] % p * a[i5] % p のように毎回 
 余りを取れば最大値を 10^18 程度に抑えられるがそれでも 2^53 - 1 を上回ってしまう 
 ◦ 64bit 整数型を扱える言語(C++, Java, Rust など)はこの方法で正解することが
 できる(問題の想定解もこの方法)
 9
  5. 諦めない • 結局
 ◦ number 型同士の計算のまま
 ◦ 計算過程で一度も2^53-1を上回ることなく 
 ◦

    x * y % p (x, y, p は 10^9 以下の正の整数)を計算 
   できればいいということ
 
 • やってやろうじゃないか!
 16
  6. 式変形① • 各数値は 10^9 < 2^30 なので高々30bit 
 • xを32bit整数型で表したときの上位12bitをa,

    下位20bitをb として 
 x = a * 2^20 + b (a<2^10, b< 2^20) 
 と表す
 • 同様に
 y = c * 2^20 + d (c<2^10, d< 2^20) 
 と表す
 17
  7. 式変形② x * y % p = (a * 2^20

    + b) * (c * 2^20 + d) % p 
      = { a * c * (2^40) + a * 2^20 * d + b * (c * 2^20 + d) } % p 
      = {a * c * (2^40 % p) + a * 2^20 * d + b * (c * 2^20 + d) } % p 
 
 18
  8. 式変形② x * y % p = (a * 2^20

    + b) * (c * 2^20 + d) % p 
      = { a * c * (2^40) + a * 2^20 * d + b * (c * 2^20 + d) } % p 
      = {a * c * (2^40 % p) + a * 2^20 * d + b * (c * 2^20 + d) } % p 
 
 • a * c * (2^40 % p) < 2^10 * 2^10 * 2^30 = 2^50 
 • a * 2^20 * d < 2^10 * 2^20 * 2*20 = 2^50 
 • b * (c * 2^20 + d) < 2^20 * 2^30 = 2^50 
 
 19
  9. 式変形② x * y % p = (a * 2^20

    + b) * (c * 2^20 + d) % p 
      = { a * c * (2^40) + a * 2^20 * d + b * (c * 2^20 + d) } % p 
      = {a * c * (2^40 % p) + a * 2^20 * d + b * (c * 2^20 + d) } % p 
 
 • a * c * (2^40 % p) < 2^10 * 2^10 * 2^30 = 2^50 
 • a * 2^20 * d < 2^10 * 2^20 * 2*20 = 2^50 
 • b * (c * 2^20 + d) < 2^20 * 2^30 = 2^50 
 
 できたぁぁ!!!!!!!!
 20
  10. EOF