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

第8回ゆるふわオンサイト 解説スライド

Avatar for forcia_dev_pr forcia_dev_pr
June 10, 2025
46

第8回ゆるふわオンサイト 解説スライド

Avatar for forcia_dev_pr

forcia_dev_pr

June 10, 2025
Tweet

Transcript

  1. 第8回ゆるふわオンサイト 
 解説スライド 
 1
 運営メンバー: dokin, ayaoni, prd_xxx, momohara,

    siro53, ochiaigawa(他協力4名) Special Thanks: tempura0224, Tallfall, kichi2004
  2. 目次
 2 • A - Progress Report Decreasing...
 • B

    - Edible Card Game
 • C - ADD MUL MAX
 • D - Range Mod Query
 • E - Insert or Swap
 • F - 2SAT ?
 • G - Unique Factorization ?
 • H - Many Count Middle Array Problem
 • 各問題FA・AC数
 • writer/tester

  3. A - Progress Report Decreasing...
 3 問題概要
 ゴリ太郎君の仕事の進捗は i日目に 10^(1-⌊(i-1)/9⌋)

    ずつ増えます。
 D日後の進捗の合計はいくらでしょう。
 制約 (部分点) 
 • 1 ≦ D ≦ 9
 制約
 • 1 ≦ D ≦ 1000
 

  4. A - Progress Report Decreasing...
 4 式を観察:
 10^(1-⌊(i-1)/9⌋) はややこしいですが以下のようになっています
 •

    1 ≦ i ≦ 9 のとき、 10^(1-0) = 10^1 = 10
 • 10 ≦ i ≦ 18 のとき、 10^(1-1) = 10^0 = 1
 • 19 ≦ i ≦ 27 のとき、 10^(1-2) = 10^(-1) = 0.1
 • 28 ≦ i ≦ 36 のとき、 10^(1-3) = 10^(-2) = 0.01
 • 37 ≦ i ≦ 45 のとき、 10^(1-4) = 10^(-3) = 0.001
 • …
 i が 9 増えるごとに位が下がっていく! 

  5. A - Progress Report Decreasing...
 5 答えを観察:
 
 
 


    
 
 …
 
 D 1 2 3 4 5 6 7 8 9 0+ 10 20 30 40 50 60 70 80 90 9+ 91 92 93 94 95 96 97 98 99 18+ 99.1 99.2 99.3 99.4 99.5 99.6 99.7 99.8 99.9 27+ 99.91 99.92 99.93 99.94 99.95 99.96 99.97 99.98 99.99 36+ 99.991 99.992 99.993 99.994 99.995 99.996 99.997 99.998 99.999
  6. A - Progress Report Decreasing...
 6 部分点解法 
 • 1

    ≦ i ≦ 9 のとき、 10^(1-0) = 10^1 = 10
 1日に 10 ずつ増えるので、10 * D が答え
 
 D 1 2 3 4 5 6 7 8 9 0+ 10 20 30 40 50 60 70 80 90
  7. A - Progress Report Decreasing...
 7 解法
 • 1 ≦

    i ≦ 9 のとき、 10^(1-0) = 10^1 = 10
 ◦ 10 * D 
 • 10 ≦ i ≦ 18 のとき、 10^(1-1) = 10^0 = 1
 ◦ 90 + 1 * (D-9)
 • 19 ≦ i ≦ 27 のとき、 10^(1-2) = 10^(-1) = 0.1
 ◦ 99 + 0.1 * (D-18)
 • 28 ≦ i ≦ 36 のとき、 10^(1-3) = 10^(-2) = 0.01
 ◦ 99.9 + 0.01 * (D-27)
 • …
 みたいな感じで計算したいが...

  8. A - Progress Report Decreasing...
 8 注意点
 • 普通の浮動小数点数型 (float

    や double等) を使うと精度が足りずWAになるの で注意!
 ◦ 倍精度でもせいぜい有効桁数が16桁ぐらい、本問題では112桁の精度を必要とする 
 ◦ (Python の Decimal を使ってもデフォルトの桁数では足りないが、112桁以上に設定 すると通せる別解もあり)
 • 文字列で処理しよう!

  9. A - Progress Report Decreasing...
 9 writer解法 
 • D

    ≦ 18 は小数点がつかないので計算で処理しておく
 • D ≧ 19 のとき、(D-19) を 9で割った商をx, あまりをyとする
 ◦ “99. {9をx個並べたもの} {y+1}” が答えとなる 
 D 1 2 3 4 5 6 7 8 9 18+ 99.1 99.2 99.3 99.4 99.5 99.6 99.7 99.8 99.9 27+ 99.91 99.92 99.93 99.94 99.95 99.96 99.97 99.98 99.99 36+ 99.991 99.992 99.993 99.994 99.995 99.996 99.997 99.998 99.999
  10. A - Progress Report Decreasing...
 10 tester解法 
 • 桁和がDであることを利用する!


    • 答えの文字列 “” に、D > 9 である限り
 ◦ “9”を追加する
 ◦ Dから9を引く
 • 最後にDを追加する
 • 文字列が1桁の場合は”0”を追加する、3桁以上の場合は2桁目に”.”を挿入す ることを忘れずに

  11. B - Edible Card Game
 12 解法
 結論:常に手持ちの中で最大のカードを出し続けるのが最善 
 証明


    自分の手持ちのうち最大の値をx、相手の手持ちのうち最大をyとする
 • x > y のとき、そのラウンドで必ず勝てるのでxを出すべき
 • x = y のとき、x以外のカードを出すと負けるのでxを出すべき
 • x < y のとき、何を出しても負け
 → 常にxを出すのが最善!

  12. C - ADD MUL MAX
 14 問題概要
 長さ N の

    正整数列 A[1], A[2], ... , A[N] が与えられます。 
 次の 2 種類の操作をそれぞれ高々 1 回ずつ行い、A[1] + A[2] + ... + A[N] を最大化せよ 
 ただし操作1と操作2を両方やる場合は、必ず操作1→操作2の順で行う 
 操作1: [l, r] を選んで、A[l], A[l+1], ... , A[r] の各要素に + X する 
 操作2: [l, r] を選んで、A[l], A[l+1], ... , A[r] の各要素に × Y する 
 制約
 • 1 ≦ N ≦ 2 × 10^5 
 • -10^5 ≦ X, Y, A[i] ≦ 10^5 

  13. C - ADD MUL MAX
 15 解法1: 頑張って場合分けする方針 
 X

    の値について考えると、3 種類考えられます。 
 1)X = 0
 2)X > 0
 3)X < 0
 それぞれについて考えていきます。 
 

  14. C - ADD MUL MAX
 16 1)X = 0 の場合


    操作1 をどのように施しても数列A は変わりません。そのため、数列A に対して操 作2 を施した場合の増加分の最大値を求めます。
 (解法★)
  15. C - ADD MUL MAX
 17 2) X > 0

    の場合
 X > 0 のの時、Y ≧ 0 か Y < 0 の場合わけが必要です。
 2-1) Y ≧ 0 の場合(部分点ケース含む)
 A の全ての要素に対して操作1 を施すのが最適です。
 そのため、(A[1] + X, A[2] + X, … , A[N] + X) とした配列に対して、(解法★)により 増加分の最大値が求まります。

  16. C - ADD MUL MAX
 18 2-2)X > 0 かつ

    Y < 0 の場合、3つのパターンに分類されます
 2-2-1) 操作1をしない
 
 
 2-2-2) Aの要素全てに操作1をしてから、部分的に操作2をする
 
 いずれもX=0の場合の 解法で求まります。

  17. C - ADD MUL MAX
 19 2-2)X > 0 かつ

    Y < 0 の場合(入出力例2のケース)
 2-2-3)
 
 仮にA[1] … A[L+j](L+j < R)まで操作1 を適用すると、操作2により
 Y × jX だけ損してしまうので、区間を重複させる必要がありません。操作1 を適用 する区間と操作2 を適用する区間は必ず隣接します。
 そのため、(解法★)を配列の後ろからやり、A[i], … A[N] の間の区間に対して操 作2を適用した時の増加分の最大値を各i に対して求めれば良いです。
 逆のパターンもあります。

  18. C - ADD MUL MAX
 20 3)X < 0 の場合


    3-1) Y ≧ 0 の場合(部分点ケース含む)
 X < 0, XY ≦ 0 より、操作1 をやる必要がないため、(解法★)でそのまま解けま す。
 3-2) Y < 0 の場合
 実は操作1を適用する区間と操作2を適用する区間は完全に一致します。
 

  19. C - ADD MUL MAX
 21 3-2) 仮に[1, M] に操作1,

    [L, R] に操作2を適用すると...
 A[i] に操作1、操作2を順に適用させたとき、(A[i] + X) × Y - A[i] だけ増加するた め、(解法★)でこの場合も解くことができます。
 以上、いずれの場合でもO(N)でこの問題を解けました。 

  20. C - ADD MUL MAX
 22 解法2: DPで解く方針 
 次のような状態を持つDP(通称「耳DP」と呼ばれるもの)をします。

    
 dp[i 番目まで見た][ 操作1をまだ開始していない(0) / 操作1を適用している(1) / 操作1を終えた(2) ][操作2 をまだ開始していない(0) / 操作2を適用している(1) / 操作2を終えた(2) ]:=A[1]+A[2]+...+A[i]の最大値 
 
 計算量はO(N)です。 
 
 イメージ図

  21. D - Range Mod Query
 23 問題概要
 長さ N の正整数列

    A[1], A[2], … , A[N] に対して Q 個のクエリを処理する 
 i 番目のクエリでは l[i], r[i] (1 ≦ l[i] < r[i] ≦ N) が 与えられ、以下を計算する: 
 • (... ((A[l[i]] % A[l[i] + 1]) % A[l[i] + 2]) ...) % A[r[i]] 
 制約
 • 2 ≦ N ≦ 1.5 × 10^5 
 • 1 ≦ Q ≦ 1.5 × 10^5 
 • 1 ≦ A_i ≦ 10^9

  22. D - Range Mod Query
 24 解法(TLE) 
 クエリごとに、以下の疑似コードのように O(N)

    かけて計算する 
 全体の計算量は O(NQ) となり、今回の問題の制約の上では TLE となる 
 
 for i := 1,2, … ,Q do ans := A[l[i]] for j := l[i] + 1, l[i]+2, … ,r[i] do ans := ans % A[j] print(ans) 
 

  23. D - Range Mod Query
 25 解法(AC) 
 疑似コード4行目の計算において ans

    < A[j] の時、計算の前後で ans の値は変化しない 
 → ans ≧ A[j] の時だけ ans := ans % A[j] を計算することにしても答えは変わらない 
 
 ans ≧ A[j] になる時は何回ぐらいかを見積もってみましょう! 

  24. D - Range Mod Query
 26 解法(AC) 
 ans ≧

    A[j] となる回数は O(log max(A_i)) 回であると見積もれます(有名事実?) 
 (証明) 
 x = ans % A[j] とすると、
 • A[j] > ans / 2 の時
 x ≦ ans - A[j] < ans - ans / 2 = ans / 2 
 • A[j] ≦ ans / 2 の時
 A[j] ≦ ans / 2 より x < A[j] ≦ ans / 2
 → よって x ≦ ans / 2、つまり ans ≧ A[j] の時あまりを計算するたびに ans の値は 1/2 以下になる
 

  25. D - Range Mod Query
 27 解法(AC) 
 ans <

    A[j] の時は無視して ans ≧ A[j] の時だけ計算することを効率良くシミュレーションできればよい。 
 ans ≧ A[j] なる j を求めるのは、区間最小値を計算する segtree 上の二分探索を用いることでO(log N) で計算出来る。
 
 よって、クエリごとに O(log N log max(A_i)) で計算出来る。 
 全体として O(Q log N log max(A_i)) でこの問題を解くことが出来ました。 
 
 

  26. E - Insert or Swap
 28 問題概要
 N 個のボールと空の箱が1つあり、ボール i

    には非負整数 A_i が書かれている 
 i=1,2,...,N の順に 操作1 or 操作2 のいずれかを行う
 ・操作1 : ボール i を箱に入れる。ボール i を箱に入れる前に箱に入っていたボールの個数が x のとき、コ ストは x かかる
 ・操作2 : 箱に入っているボールを 1 つ選び、ボール i と swap する。ボール i を箱に入れる前に箱に入っ ていたボールの個数が x、ボール i と swap したボールに書かれている非負整数が y のとき、コストは x+y かかる(箱に1つ以上ボールがあるときしかこの操作は出来ない) 
 全ての操作を終えた後に箱に入っているボールを K 個にしたいとき、コストの合計を最小化せよ 
 

  27. E - Insert or Swap
 29 考察1
 • 操作1 では箱の中のボールの個数は

    1 個増える 
 • 操作2 では箱の中のボールの個数は変わらない 
 • 箱の個数は最終的に K 個にしなければならない 
 → 操作1 を行う回数は K 回、操作2 を行う回数は N-K 回で固定される 
 
 

  28. E - Insert or Swap
 30 考察2
 最初すべて 操作1 を行うことにして、どのボールを操作2で捨てるとよいかを考える

    
 全て 操作1 を行うことにすると、コストの和は 0+1+...+(N-1) = (N-1)*N/2 
 次に、ボール i を 操作2 にするときのコストの差分を考える 
 • 箱の中に入っているボールの個数分かかるコストを タイプx
 • 捨てるボールに書かれている非負整数だけかかるコストを タイプy
 とする

  29. E - Insert or Swap
 31 考察2-x 
 ボール i

    で操作1ではなく操作2をすることにしたときの、コストの差分を考える 
 • ボール i+1, i+2,..., N にかかる タイプx のコストが -1 減る
 このときのコストの合計は、操作2が i=2,3,...,N でしか出来ないことに注意すると 
 N-(i+1)+1を小さい順にN-K個選んだ分だけ減る 

  30. E - Insert or Swap
 32 考察2-y 
 操作2 によって捨てられるボールに書かれている整数分、コストがかかる

    
 捨てられるボールは i=1,2,...,(N-1) に限られることに注意すると、タイプy の合計は 
 i=1,2,...,N-1 の中から A_i だけ減る 

  31. E - Insert or Swap
 33 コストをまとめると、定数項を無視して 
 i=1,2,...,N-1について A_i

    - (N - (i + 1)) をソートして、昇順にN-K個選ぶのが最適 
 O(NlogN) で解ける。

  32. F - 2SAT ?
 34 問題概要
 - A_i = X_i

    or A_i = Y_i
 - A_i ≠ A_j
 以下の条件を満たす数列 A の個数を数えよ

  33. F - 2SAT ?
 35 部分点満点の共通の考察
 X = (1,2,3,4), Y

    = (2,1,4,3) のケース
 A_1
 A_2
 A_3
 A_4
 A_iがマッチング可能な数字の間に線を引い て二部グラフを作る
 (多重辺がないように作る)
 赤い頂点を被覆するようなマッチングの数え 上げが答え
 1
 2
 3
 4
 本問題の入力では連結成分が複数がありえ るので、各連結成分で数え上げて積が答え になる。
 (以後、グラフが連結とする)
 赤の頂点の次数は2以下!

  34. F - 2SAT ?
 36 部分点と満点解法の差分
 A_1
 A_2
 1
 2


    A_1
 1
 2
 X = (1,2), Y = (2,1) 
 X = (1), Y = (2) 
 部分点は、赤がN頂点で、青はN以下なので、 (マッチングがあるなら) 青は全て使う 
 満点は青は使わなくてもいい頂 点がある

  35. F - 2SAT ?
 37 部分点解法
 A_1
 A_2
 1
 2


    1. 赤も青も全て使うので、全体で次数1の点があ ればマッチング確定
 2. マッチングした点を除く
 3. 孤立点がうまれたら答えは0 。生まれなかっ たら1に戻る
 4. 1ができなくなったら、実はcycleになっている ので、マッチングは2通り
 3
 A_3
 X = (1,2,3,4), Y = (2,3,4,3) 
 4
 A_4
 左の例だと
 (A_1,1) (A_2,2)がマッチングして、長さ4の cycleがのこる

  36. F - 2SAT ?
 39 観察1
 
 (青の頂点の数) - (赤の頂点の数)

    <=1 が成立
 証明: 帰納法など 
 (気持ち的には青の頂点を追加しようとしても、赤の頂点の次数の制約があるからそんなに追加できないみたいな)
 特にcycleを作ろうとすると 青 - 赤が減る

  37. F - 2SAT ?
 40 観察2
 
 各連結成分は実は以下の4パターンに分類される。
 青 -

    赤 = 1で木
 青 - 赤 = 0で木
 青 - 赤 = 0でcycleが ちょうど1つ
 青 - 赤 <0 
 (マッチングなし)
 (部分点はマッチングがある なら、真ん中2つのみ)

  38. F - 2SAT ?
 41 観察2の正当性 (略証)
 
 結局のところ、ある連結成分に辺と頂点を追加して、cycleを作ろうとすると、青 の頂点を追加したときに、元々その連結成分に存在する赤の頂点同士を結ぶ

    必要があって、青 - 赤が減る
 青 - 赤 <=1 であり、青 - 赤 = 1の場合cycleを作ることができない。 (cycleを作 ろうとすると、青 - 赤が減る)
 青 - 赤 = 0のとき、cycleは高々が1つしかつくれない。 (cycleを2つ以上作ろう とすると、青 - 赤 < 0になる。)

  39. F - 2SAT ?
 42 満点解法1 (W解) 
 
 木DPでマッチングの

    個数が分かる
 マッチングなし
 木DPでO(N)
 cycleの頂点はcycle内 部でマッチングさせる必 要があって2通りで、あと は木DPでマッチングの 個数が分かる
 木DPでマッチングの 個数が分かる

  40. F - 2SAT ?
 43 満点解法2 (T解) 
 
 マッチングの個数

    = 青の頂点数
 実はDPしなくても分かる!
 マッチングの個数 = 2 
 マッチングの個数 = 1 
 マッチングの個数 = 0 

  41. F - 2SAT ?
 44 満点解法2の正当性
 
 青 - 赤

    = 0で木のケースでマッチングが一意に存在することを示す
 二部グラフなので、赤の頂点の次数の総和 = 辺の総数で、偶数頂点なので、辺 の総数は奇数になる。赤の頂点で次数が奇数のものが存在するが、赤の頂点 の次数は2以下なので、次数1のものが存在する (これは葉) 
 葉を一意にマッチングして、マッチングした頂点を消すと、青 - 赤 = 0の頂点数 の少ない木の問題に帰着できるので帰納的にわかる。
 
 青 - 赤 = 0かつcycleがある場合、cycle内部で2通り +周辺が木となる。
 青 - 赤 = 1の場合は、使わない青の頂点を決めるとマッチングが一意に存在す る。

  42. F - 2SAT ?
 45 余談
 
 2SATという問題がある
 (x ∨

    y) ∧ (¬x ∨ z) ∧ (¬y ∨ ¬z)  
 全体でx,y,zに真理値を割り当てして、全体を真にする。
 第一節は x = true or y = trueということ
 充足解の存在判定をするのは線形時間でできる。
 ACL参照:https://zer0-star.github.io/Nim-ACL/document_ja/twosat.html
 充足解の数え上げは #P完全と呼ばれており、P≠NPのもとでは、多項式時間で解 けない 
 参照: https://en.wikipedia.org/wiki/2-satisfiability 
 (途中二部グラフの完全マッチングの数え上げに帰着していたが、これも#P完全) 
 
 本問題では、特殊な制約があるので解ける 

  43. 問題概要 数列 X, Y の全ての並び替えに対する↓の答えの和 mod 998244353 Count Middle Array

    Problem 全ての i について X[i] <= A[i] <= Y[i] をみたす数列の個数 H - Many Count Middle Array Problem
 55
  44. 言い換え① Count Middle Array Problem の答えは ∏ (Y[i] - X[i]

    + 1) if すべての i で Y[i] >= X[i] else 0 Y にあらかじめ 1 を足しておくことで、以下では ∏ (Y[i] - X[i]) if すべての i で Y[i] > X[i] else 0 として考える。すると、問題は以下のように言い換えられる すべての i で Y[i] > X[i] となるような並び替えに対する ∏ (Y[i] - X[i]) の和 
 H - Many Count Middle Array Problem
 56
  45. 言い換え② ∏ (Y[i] - X[i]) をそのまま扱うのは大変。展開して、以下のように考える 各項から Y[i] or -X[i]

    のどちらかを選んで積を取る。 選び方全て(2^N通り)に対するこの積の総和 この考えを使うと、問題はさらに言い換えられる すべての i で Y[i] > X[i] となるように並び替えたあと、Xをすべて -1 倍し、 各 i ごとに X[i] とY[i] のどちらかに丸をつける。丸をつけた要素の積 の総和 H - Many Count Middle Array Problem
 57
  46. そしてDPへ X, Y をそれぞれ昇順に並べて 小さいものから取り出していく。 X: 残りの場所に自由に選べる Y: すでにXがある場所に置ける dp[X,Yから取り出した合計個数][まだペアが決まっていなくて丸のついている

    Xの数] を考えることで、いい感じに遷移できる。 よって O(N^2) で解くことができた。 H - Many Count Middle Array Problem
 58 3 2 5 1 4 7 4 X = {1, 2, 3, 4, 5, …}
 Y = {4, 7, 10, …}
 X
 Y

  47. 各問題のFA・AC数
 59 問題 オンサイト FA 全体FA AC数 A - Progress

    Report Decreasing… potato167 potato167 53/53 B - Edible Card Game uruzunyaa uruzunyaa 55/55 C - ADD MUL MAX potato167 potato167 30/36 D - Range Mod Query potato167 potato167 40/42 E - Insert or Swap potato167 potato167 29/33 F - 2SAT ? potato167 wasureta 23/24 G - Unique Factorization ? potato167 tute7627 3/4 H - Many Count Middle Array Problem potato167 potato167 4/5
  48. 60 問題 writer tester A - Progress Report Decreasing… prd_xxx

    momohara B - Edible Card Game prd_xxx momohara C - ADD MUL MAX ###, tempura0224 ochiaigawa D - Range Mod Query siro53 ayaoni E - Insert or Swap siro53 ochiaigawa F - 2SAT ? ### siro53 G - Unique Factorization ? ayaoni ochiaigawa H - Many Count Middle Array Problem tempura0224 ### writer/tester