ロマン開花學園の開花タッグ計算式 —— 狙わなくてよさそう パワプロアプリ

この記事について

キャラのタッグボーナス・練習効果UPの数値は GameWith「全キャラ絞り込み検索ツール」 のデータを参照しています。

種の仕様は GameWith「ロマン開花学園の攻略まとめ」、得意練習による優遇は 公式の育成ガイド、半減ルールは りょーつーさんの動画 を参照しました。各位に感謝します。

なお、本記事の計算式・分析・結論は、誤っている可能性があります。

ロマン開花學園の「開花タッグ」で経験点がいくら増えるのか、実測で計算式を特定した。

結論から言うと、開花タッグを狙って練習を選ぶ必要はない。花1個で乗るのは種5個分ほどで、練習場所そのものによる差のほうがよほど大きいからだ。デッキを組むとき、二種練習より単練をわずかに優先する、くらいの位置づけになる。

前提となる「開花力」と「ベース」の話は前記事にまとめている。

ロマン開花学園の練習経験点、計算式が分かった ── デッキ編成が全て パワプロアプリ - こきず

※ 投手育成で検証。野手でも同じかは未確認。


結論を3行で

  1. 開花タッグの上乗せは「発動ボーナス」(練習ごとに決まった経験点1つに入る)と「花ボーナス」(花のある経験点に入る)の2種類
  2. 単練・二刀流は二種練習の1.5倍。単練なら発動ボーナスが種3.75個分、花ボーナスが花1個あたり種1.46個分
  3. 花1個なら合計種5個分ほど狙って練習を選ぶほどの差にはならない

この記事を読む前に

開花タッグの話に入る前に、前提を4つだけ押さえておく。すでに知っている人は読み飛ばして構わない。

前提1:種1個分の値

練習画面には2種類の数字が出る。黄色が通常の練習経験点、赤茶色が「才能の種」による経験点だ。本記事が扱うのは赤茶色のほうだけになる。

この赤茶色の分は、種1個ごとに一定量が入るという形をしている。その1個分の値は前記事で特定した式で決まる。

種1個分 = ( ベース + その練習にいるキャラの開花力の合計 ) ÷ 2

ベースはデッキ全員の開花力の合計で決まる値。開花力はキャラごとにタッグボーナスと練習効果UPから算出される値。詳しくは前記事を参照してほしい。

以降の説明はすべて「種○個分」という単位で書く。 実際の点数は、これに種1個分の経験点を掛ければ出る。

前提2:種の数え方

種は2か所から出てくる。

出どころ 個数
練習場所 計4個固定(2種類×2個、または1種類×4個)
参加キャラの所持分 1人あたり0〜2個(種と花を合わせて)

練習場所に4個出るのはGameWithの攻略記事にも記載がある。キャラが持っている種は、練習画面でキャラの立ち絵の右下にアイコンとして出る。

なお「才能の花」も、基本部分では種1個として数える。そのうえで別途、花ボーナスが乗る。

前提3:半減ルール

練習ごとに「得られる経験点」が決まっており、それ以外は種経験点が半分になる。

練習場所 半減しない経験点
球速 筋力・技術・精神
コントロール 技術・精神
変化球 技術・変化球・精神
スタミナ 筋力・精神
守備 敏捷・技術・精神
メンタル 技術・精神

見分け方は簡単で、該当練習で取得できない経験点(練習画面で素点(黄色の数字)が入っていない経験点)は半減対象になる。

半減の仕組みは、りょーつーさんの動画 【超重要】絶対覚えるべき経験点の稼ぎ方3選!コレで世界が変わります の1:30あたりでも解説されている。上の表は本記事の実測によるもの。

前提4:スタミナ・メンタル練習の補正

半減ルールとは別に、練習の種類そのものによる補正もかかる。

練習場所 補正
スタミナ 0.9倍
メンタル 0.5倍
球速・コントロール・変化球・守備 なし

メンタル練習は体力が回復する代わりに、種経験点が半分しか入らない。


開花タッグとは

練習場所に花があり、かつその練習と得意練習が一致するキャラがいると発動する。発動すると2種類のボーナスが上乗せされる。

種類 どこに入るか
発動ボーナス その練習のメイン経験点1つだけ
花ボーナス 花のある経験点に、花の数だけ

花が1個もない練習では発動しない。 得意練習が一致するキャラがいても、花がなければ何も起きない。

花はどこから来るか

才能の花は開花試合に勝利すると獲得でき、イベキャラ以外のチームメイトに付与される(詳しくは GameWith「ロマン開花学園の攻略まとめ」 を参照)。

つまり、どの練習に花が出るかはこちらから選べない。開花タッグを積極的に狙いにくいのは、これが理由になる。


キャラのタイプ

倍率はキャラのタイプで変わる。公式の育成ガイドにはこう書かれている。

得意練習が1つのみのキャラ(いわゆる二刀流含む)が完全開花タッグを発生させた場合、さらに経験点がアップします

つまり判定は「投手の得意練習が1つか2つか」で行う。本記事では通称にならって次のように呼ぶ。

呼び方 意味
単練 投手の得意練習が1つだけのキャラ
二刀流 投手と野手の得意練習を1つずつ持つキャラ。投手の得意練習は1つなので単練と同じ扱い
二種練習 投手の得意練習を2つ持つキャラ

開花タッグ発動時は、単練・二刀流のほうが多くの経験点を得られる。 ただし差は1回あたり種1.74個分で、劇的な違いではない。


発動ボーナス

開花タッグが発動すると、その練習ごとに決まった経験点1つだけに上乗せが入る。これをメイン経験点と呼ぶことにする。

練習場所 メイン経験点 単練・二刀流 二種練習 補正
球速 筋力 種3.75個分 種2.50個分 なし
コントロール 技術 種3.75個分 種2.50個分 なし
変化球 変化球 種3.75個分 種2.50個分 なし
守備 ※ 技術 ※ 種3.75個分 ※ 種2.50個分 ※ なし ※
スタミナ 精神 種2.625個分 種1.75個分 3割減
メンタル 精神 種0.375個分 種0.25個分 9割減

※ 守備練習は開花タッグの実測がない。メイン経験点も倍率も推測。

スタミナ練習では3割、メンタル練習では9割が差し引かれる。 メンタル練習の発動ボーナスは実質ないに等しい。

複数のキャラが一致している場合は、有利なほう(単練・二刀流)が採用される。

実際の画面で見てみる。イチロー(二刀流・投手の得意練習はコントロール)がコントロール練習で開花タッグを起こしたときのもの。種1個分は3,540点だった。

①の技術20,384点のうち、種2個分の約7,090点は開花タッグと関係なく入る分。残りの約13,300点が発動ボーナスにあたる。3.75 × 3,540 という計算になる。

デッキの強さとの関係

「種何個分か」という倍率は、常に同じ。変わるのは種1個分の値のほうで、こちらはデッキの開花力合計が高いほど上がる。

つまりデッキを強くすれば、開花タッグで入る経験点も比例して増える。倍率は据え置きのまま、実額だけが伸びる。


花ボーナス

花1個あたりの取り分。練習場所にある花の総数で決まる。自分の経験点に入る量は「これ × その経験点の花の数」。

練習場所の花の総数 単練・二刀流 二種練習
1個 種1.46個分 種0.98個分
2個 種0.90個分 種0.60個分
3個 種0.68個分 種0.45個分
4個以上 不明 不明

単練・二刀流は二種練習のちょうど1.5倍。発動ボーナスと同じ比率になっている。

例として、練習場所に花が2個あり、2個とも精神についている場合。単練・二刀流のキャラなら 種0.90個分 × 2個 = 種1.8個分。種1個分が3,500点なら精神経験点に約6,300点が上乗せされる。

  • 花が増えるほど1個あたりは減るが、合計は増える
  • 発動ボーナスと違い、スタミナやメンタルの3割減・9割減はかからない
  • 同じ経験点に花が複数集まると多少の加点がありそうだが、最大でも種0.1個分(数百点)なので上の表では省略した

練習改革がある練習の場合

開花タッグが発動している場合だけ、改革対象の経験点(例:コントロール練習改革の変化球)にさらに上乗せが入る。

キャラのタイプ 上乗せ
単練・二刀流 種1.125個分
二種練習 種0.75個分

開花タッグが発動していない練習では、この上乗せは入らない。


計算例

実際の画面で確かめてみる。条件は次のとおり。

  • 改スタミナ練習 Lv1
  • 参加イベキャラは月島(二刀流、得意練習はスタミナ)
  • 精神の花が1個、変化球の練習改革あり
  • 種1個分 = 3,510点

種の内訳はこうなっている。

出どころ 内容
練習場所 筋力2個・技術2個
月島が所持 変化球2個
モブが所持 技術2個・精神2個・精神の花1個

画面の赤茶色の数字が種経験点。①〜④の内訳は次のとおり。

① 筋力 6,319点 種2個 × 0.9(スタミナ練習の補正)= 種1.8個分

② 技術 6,319点 種4個 × 0.9 × 0.5(スタミナ練習では技術が半減)= 種1.8個分

③ 変化球 10,268点 種2個 × 0.9 + 練習改革の上乗せ1.125 = 種2.925個分

④ 精神 23,831点(メイン経験点) (種2個 + 花1個) × 0.9 + 発動ボーナス2.625 + 花ボーナス1.46 = 種6.79個分

①と②が同じ点数なのは偶然ではない。筋力は種2個が満額、技術は種4個が半減で、どちらも実効1.8個分になっている。

この練習で開花タッグによって上乗せされたのは、③の1.125と④の2.625+1.46。合計すると種5.2個分、約18,300点になる(練習改革の分を含む)。


実戦でどう使うか

結論から言うと、練習を選ぶ基準としては優先度が低い

開花タッグで乗るのは、単練かつ花が1個なら種5個分ほど(発動ボーナス種3.75個分 + 花ボーナス種1.46個分)。決して小さくはないが、どの練習を選ぶかで生じる差のほうが大きいことが多い

練習を選ぶときの優先順位

  1. その練習に種と花が何個あるか(練習場所の4個 + 参加キャラの所持分)
  2. 半減されない経験点に種が乗っているか
  3. スタミナ・メンタル練習ではないか
  4. 開花タッグが出ているか

開花タッグは、1〜3で差がつかないときの判断材料くらいでいい。

デッキを組むときは

単練・二刀流は、発動ボーナス・花ボーナスとも二種練習の1.5倍。開花タッグ1回あたり種1.74個分の差になる。種1個分が3,500点なら約6,000点。

デッキ編成の優先順位は、まず開花力(タッグボーナスと練習効果UP)が高いキャラ。開花力が同程度なら単練・二刀流、という順番がよいだろう。

実例

同じデッキ・同じターンで別々の練習を測ると、こうなった。

練習 開花タッグ その練習で入る種経験点の合計
コントロール なし 24,556
メンタル あり 17,770

タッグが出ているメンタルより、出ていないコントロールのほうが多い。

メンタル練習が弱いのには理由がある。この練習は種経験点そのものが半分になるうえ、発動ボーナスも9割減。タッグが出ても乗るのは 発動ボーナス0.375 + 花ボーナス1.46(花ボーナスには9割減がかからない)= 種1.84個分にしかならない。

一方、コントロールや変化球でタッグが出たときは、同じターンの他の練習より種2〜7個分多くなった。開花タッグ自体が弱いのではなく、スタミナとメンタルで大きく目減りするというだけの話だ。


注意書き

以下は未確認、または注意が必要な点。

  • 守備練習だけは開花タッグを観測できていない。 メイン経験点も倍率も推測
  • 経験点は小数点処理の関係で数点ずれることがある
  • 投手育成で検証した。野手でも同じ式が成立するかは未確認

どの実測からこう判断したのかは、開花タッグの検証編として別途まとめる予定。

前提となる開花力とベースの話は前記事へ。

ロマン開花学園の練習経験点、計算式が分かった ── デッキ編成が全て パワプロアプリ - こきず

ロマン開花学園の練習経験点、どうやって計算式を割り出したか【検証編】 パワプロアプリ

別記事で出した計算式が、どんな実測データから導かれたのかを書く。
各種検証時の画像は貼れたら貼ります

ロマン開花学園の練習経験点、計算式が分かった ── デッキ編成が全て - こきず

開花力 = [ 23 + 0.59 × Max(0, タッグボーナス − 150) ] × [ 1 + 0.09 × Max(0, 練習ボーナス − 10) ]

練習での種2個あたりの獲得経験点 = ベース + その練習にいるキャラの開花力の合計
ベース = 下限値 + 5.02 × Max(0, Σ開花力 − 284)

計算式そのものと、デッキ編成への結論は前記事にまとめてある。


測定の方法

すべて「種2個あたり・経験点1種類あたり」に換算して記録した。

  1. デッキを組み、イベキャラが誰も参加していない練習(モブのみ)の経験点を測る = ベース
  2. 同じ練習にイベキャラを1体だけ参加させて測る
  3. その差が、そのキャラの寄与 = 開花力

練習Lvは固定。やる気・モブ人数は無関係と分かったので途中から記録していない。


ステップ1:タッグボーナスだけを動かす

練習ボーナスを持たないキャラを1体だけ練習に置き、経験点の増分を測った。

キャラ タッグ 増分
ドライブ Lv1 80 23
カグヤ Lv50 120 23
日向 Lv42 150 23
月島 Lv50 160 28
猪狩 Lv50 175 37
大谷 Lv45 200 53
大谷 Lv50 240 76

タッグ150までは全部23で横ばい、そこから直線的に伸びる。傾きは 0.59

閾値を145や155に置くと、係数をどう調整しても実測値と合わない(誤差±2でも解なし)。 150ちょうどで確定できた。


ステップ2:練習ボーナスを動かす

タッグ150以下のキャラ(タッグ由来の値が23で固定される)を使い、練習ボーナスだけを変えた。

キャラ タッグ 練ボ 増分
ドライブ Lv1 80 0 23
ルナ Lv50 135 10 23
雨野 Lv45 90 15 33
白霧 Lv45 120 20 43
るも Lv50 140 30 64
イチロー Lv45 100 45 96

練習ボーナス10までは23で横ばい。 ここでも足切りがある。


ステップ3:足し算か掛け算か

ここが山場。ステップ2だけでは、タッグ由来の23に練習ボーナス分を 「足している」のか「掛けている」のか区別できない(全員23で固定されているので)。

考え方はこうだ。

  • もし足し算なら、タッグ由来の値が大きいキャラでも小さいキャラでも、 練習ボーナスによる上乗せ幅は同じになるはず
  • もし掛け算なら、上乗せ幅はタッグ由来の値に比例するはず (=タッグ由来の値で割った「倍率」が一致するはず)

そこで練習ボーナスが同じで、タッグだけが違うペアを比べた。

練習ボーナス タッグ160のキャラ タッグ150以下のキャラ 倍率の差
20 白霧Lv50 → 倍率 1.8685 白霧Lv45 → 倍率 1.8696 0.06%
30 初白百合 → 倍率 2.8028 るもLv50 → 倍率 2.7826 0.7%

倍率がぴたりと一致した。よって掛け算。 足し算モデルだと最大誤差39.7、掛け算モデルなら2.6に収まる。

しかも白霧Lv50とLv45は同じキャラのレベル違い(タッグ160と120、練習ボーナスはどちらも20)。 対照実験として理想的な組み合わせだった。


ステップ4:デッキ編成でベースが動くことの発見

イベキャラが誰も参加していない「モブのみ」の練習でも、デッキを変えると経験点が変わった。

デッキ Σ開花力 ベース実測 計算式の予測
低開花力キャラ中心 191〜240 6327 6327(下限)
高開花力2枚 344 6626 6626
高開花力3枚 387 6846 6846
高開花力4枚 452 7172 7172
高開花力5枚 549 7656 7655

キャラを1枚足したときの増分を、そのキャラの開花力で割ると、

追加したキャラ 開花力 ベース増分 増分 ÷ 開花力
白霧Lv45 44 +220 5.01
るもLv50 65 +326 5.03
イチローLv45 96 +484 5.03

きれいに5.02倍で揃う。


ステップ5:「デッキの練習ボーナス合計」説は否定された

一見すると練習ボーナスの合計で決まりそうに見えるが、決定的な反例がある。

デッキ 練ボ合計 ベース
イチロー45+るも50+雨野45+ルナ50+ドライブ1 100 6327
大西50+泡瀬50 60 6626

練習ボーナス合計が少ない方がベースが高い。

前者は全員タッグ150以下で開花力が小さく(合計240)、足切りに引っかかっていた。 タッグも込みの「開花力」でないと説明できない。


そのほか確かめたこと

項目 結果
種数への比例 チーム全体の種を3個→23個まで増やしても、種1個あたりの経験点は一定
チームの種の保有数 無関係(上と同じ検証で確認)
モブの人数 無関係。参加モブを増減させても変化なし
やる気 無関係
タッグの発生 不要。全データはタッグ未発生時のもの
複数人の参加 単純な足し算。個別に測った値の和と誤差±1で一致
デッキ合計タッグ・デッキ合計練習ボーナス ベースには影響しない(開花力の合計でのみ決まる)
デッキ枚数 影響しない(1枚デッキから5枚デッキまで同じ式で説明できた)

複数人参加が足し算であることの確認

観測 実測 個別値の和
ルナ50+ドライブ1 46 23+23 0
雨野45+ドライブ1 56 33+23 0
ドライブ1+イチロー45 119 23+96 0
雨野45+るも50 97 33+64 0
るも50+イチロー45 159 64+96 −1
大西50+泡瀬50 345 164+180 +1

未解決のこと

1. 大西Lv50だけ計算式から約2ずれる

b=0.59, k=0.09 で単独参加22観測のうち20観測が誤差±1.1に収まるが、 [超攻型]大西だけが約2低い値を出す(実測161〜164、計算式163.5)。

「各項で小数点処理をしている」「全体計算後に1回だけ処理している」といった 丸め方の違いではないかと考え、8通りの丸め構造を全探索したが、すべて解なしだった。

決定的な診断は、種2個ちょうどで実測した練習ボーナス30の3観測の傾き。

区間 傾き
初白百合(超過分10)→ 大西(超過分60) 1.600
大西(超過分60)→ 泡瀬(超過分70) 1.800

同じ練習ボーナス30なら倍率は共通のはずで、傾きも一定になるはず。 floor を入れても真の傾きは (1.58, 1.62) と (1.70, 1.90) で重ならない。 丸めの位置の問題ではない。原因は未特定。実用上は誤差1.2%なので無視してよい。

2. 足切り284の正確な位置

実測で挟めているのは Σ開花力 240〜344 の範囲だけ。 240(Σ開花力の低いデッキ)が下限に張り付き、344(大西+泡瀬)が下限を超えている、というだけで、 その間にデータがない

284という数字は、Σ開花力344〜549の4点が作る直線を延長して、下限値6327と交わる点として求めた。 4点すべてが T=283.9〜284.1 と一致するので直線の当てはまりは良いが、 「直線が下限でそのまま止まる(段差がない)」という前提のもとでの値になる。

なお284が中途半端な数字なのは、おそらく設計値ではなく導出値だからだろう。 設計されているのは「下限値」の方で、284はたまたま直線がそこを通る点にすぎない。 だとすれば、練習の種類や練習Lvを変えて下限値が変われば、 「足切りに見える位置」も動くはずだ。これは今後の検証ポイント。

3. ベースの下限値が何で決まるか

下限値 6327 は練習の種類・練習Lv・経験点の種類によって変わるはずだが、 その式はまだ分かっていない。これが経験点の97%以上を占めるので、 本当はここが一番大きなテーマになる。

4. 野手キャラの下降補正

野手キャラには開花力に下降補正がかかるという情報があるが、筆者は未検証


使ったデータについて

  • 実測は投手育成のみ。1周ごとにデッキを組み替えて、モブのみのベース値から測り直している
  • 経験点は「種2個あたり」に正規化して記録。種がちょうど2個でない練習は割り戻したため、 1の位に±1程度の誤差が乗っているものがある
  • キャラのタッグボーナス・練習効果UPは GameWith「全キャラ絞り込み検索ツール」の Lv50時の値を使用(ゲーム内のデッキ編成画面と一致することを実測で確認済み)

ロマン開花学園の練習経験点、計算式が分かった ── デッキ編成が全て パワプロアプリ

この記事について

検証のきっかけは、ありさじさんのブログ「気になる(仮)」の記事 タッグボーナスの恩恵が低い?バグ?ロマン開花學園 です。

また、キャラのタッグボーナス・練習効果UPの数値は GameWith「全キャラ絞り込み検索ツール」 のデータを参照しています。両者に感謝します。

なお、本記事の計算式・分析・結論は、誤っている可能性があります。

2026/8/14 更新

  • ベースの係数を 5.02 → 5.085 に修正しました。開花力の係数を更新した際に再計算していなかったための訂正です。あわせて、この係数から導いていた数値(編成効果の倍率、「5. 最低ラインは練習効果UP30%を6枚」の表)も更新しています。実測値そのものに変更はありません。
  • 目次を追加し、見出しと改行まわりを整理しました。

ロマン開花學園の練習で得られる経験点の計算式を、実測でほぼ解明した。

結論から言うと、このシナリオはデッキ編成でほぼ勝負が決まる。そしてタッグボーナスより練習ボーナスの方がずっと重要だった。

この記事は計算式と結論だけを書く。どんな実測データからそう判断したのかは、別記事「検証編」にまとめた。

ロマン開花学園の練習経験点、どうやって計算式を割り出したか【検証編】 - こきず

※ 投手育成で検証。野手でも同じかは未確認。


結論を3行で

  1. 各キャラは タッグボーナス練習ボーナスから「開花力」という値が決まる
  2. デッキ全員の開花力の合計が、練習経験点の土台(ベース)を決める
  3. タッグ150以下・練習ボーナス10以下の部分は完全に切り捨てられる

経験点の全体像

まず全体の形を押さえてほしい。以降の話は、すべてこの式のどこかの説明になる。

練習での種2個あたりの獲得経験点 = ベース + その練習にいるキャラの開花力の合計

経験点は種1個ごとに発生するが、比べやすいようにすべて「種2個あたり・経験点1種類あたり」の値で書く。実際の獲得量はこれに種の数を掛けて2で割ったものになる。


要点1 ── キャラの「開花力」

すべての土台になる値。キャラ1体ごとに、タッグボーナス練習ボーナス(練習効果アップ)から算出される。ロマン開花高校において高いほど有効なため、開花力と呼ぶ。

開花力 = [ 23 + 0.59 × Max(0, タッグボーナス − 150) ] × [ 1 + 0.09 × Max(0, 練習ボーナス − 10) ]

Max( ) の中は2つの値の大きいほうを取る。タッグ150以下なら左は23、練習ボーナス10以下なら右は1になる。よって最低は23、最高は[水着]泡瀬満里南で180(2026/8/8現在)。

ここが重要 ── 足切りと掛け算

  • タッグボーナスは150を、練習ボーナスは10を超えた分しかカウントされない(下回っても開花力が0になるわけではなく、タッグ側は23、練習ボーナス側は倍率1.0の最低保証がある)
  • そして両者は掛け算。片方が足切りに引っかかっていると、もう片方を伸ばしても伸び方が鈍い

要点2 ── ベースはデッキ全員の開花力合計で決まる

イベキャラが誰も練習に参加していなくても、経験点はデッキ編成で変わる。編成しているだけで効くのがポイント。

ベース = 下限値 + 5.085 × ( Σ開花力 − 284 )

  Σ開花力 = デッキのキャラ全員の開花力の合計
  ※ Σ開花力が284以下なら、ベースは下限値のまま動かない

デッキにイベキャラなしの場合

デッキに開花力の高いキャラを5体セットしたとき

下限値は練習の種類・練習Lv・経験点の種類によって変わる。筆者の測定条件(デッキにイベキャラ0体)では 6327 だった。

つまり

  • Σ開花力が284以下のデッキは、何を入れても経験点が1点も増えない
  • 284を超えると、超過分1につきベースが約5点増える
  • Σ開花力を100増やすと、ベースは約510点(下限比で 約8%)増える

実測ではこうなった。

デッキ Σ開花力 ベース
低開花力キャラ中心 191〜240 6327(下限のまま)
高開花力キャラ2枚 344 6626
高開花力キャラ3枚 387 6846
高開花力キャラ4枚 452 7172
高開花力キャラ5枚 549 7656

開花力の低いキャラで枠を埋めても、本当に何も起きない。


要点3 ── 練習に参加するとさらに上乗せ

その練習場所にイベキャラがいると、そのキャラの開花力がそのまま加算される。複数人いれば全員分が足される(単純な足し算)。

デッキに[水着]泡瀬50のみ編成

編成と参加、どっちが大事か

編成が本体。 デッキにいるだけで開花力の 5.085倍 がベースに乗るのに対し、練習に参加して上乗せされるのは 1倍分だけ。

開花力180の[水着]泡瀬満里南なら、編成しているだけで +915点、練習に参加して +180点編成の効果が約5倍ある。


デッキ編成のアドバイス

以下、投手育成で使えるキャラ 303体(得意練習に球速・コントロール・スタミナ・変化球を含むキャラ+ゼルヴィー・ハイゼンベルク)を対象に集計した。数値はすべてLv50時。

1. 同じタッグ帯なら、練習ボーナスが圧倒的に強い

タッグボーナスが同じで練習ボーナスだけ違う3体が実在するので、これが一番わかりやすい。

キャラ タッグ 練効UP 開花力
月島・堤 160 0 28
[白塵の魔女]白霧凍子 160 20 54
初白百合 160 30 81

タッグが全く同じなのに、練習効果UPだけで開花力が約3倍。

逆に、練習効果UP0で揃えてタッグだけを実質最大幅まで動かすと、こうなる。

キャラ タッグ 開花力
月島 160 28
猪狩 175 37
大谷翔平(Lv45) 200 53
[復活の二刀流]大谷翔平 240 76

2.7倍にしかならない。練習効果UPの方が振れ幅が大きい。

※ どちらの表も実測値。レベルは測定時のもので、記載のないものはLv50。

2. タッグ特化は罠。大谷翔平が11位という現実

開花力順に並べると、タッグ最高クラスの[復活の二刀流]大谷翔平(タッグ240)は11位。開花力76で、タッグ100のイチロー(95)にも、タッグ80の白霧凍子(85)にも負ける。

そもそもタッグ特化型(タッグ180以上・練習効果UP20以下)は大谷翔平ただ1体しかいない。 運営はタッグ特化キャラをほぼ作っていない。タッグの数字だけ見て編成すると確実に損をする。

3. 上位3体だけが別格。次点は練習効果UP35以上

開花力 体数 どんなキャラか
150以上 3体 泡瀬・大西・ゼルヴィー
100〜149 0体
70〜99 10体 練習効果UP35〜45、またはタッグ160・練効30
50〜69 57体 大半が「練効30・タッグ150以下」の開花力64
24〜49 58体
23 175体(58%) 置物

3位151と4位95の間に1.6倍の断絶があり、100〜149の帯には1体もいない。 上位3体を持っているかどうかで、デッキの質が階段状に変わる。

持っていないなら、練習効果UPが高いキャラを優先する。タッグは見なくていい。

4. 開花力23のキャラは完全に「置物」

タッグ150以下かつ練習効果UP10以下のキャラは、開花力が23で固定される。対象303体のうち175体(58%)がこれにあたる。練習効果UPを持たないキャラが155体もある。

置物で枠を埋めると、Σ開花力が284の足切りを超えられずベースが下限に張り付く(6枚でΣ138)。デッキ全体が死ぬ。

5. 最低ラインは「練習効果UP30%を6枚」

6枠でΣ開花力284を超えるには、平均47以上が必要。ここが意外と厳しい。

デッキ Σ開花力 ベース 下限比
上位6体 759 8742 +38.2%
7〜12位の6体 475 7298 +15.4%
練効30のキャラ6枚(開花力64) 384 6836 +8.0%
練効20のキャラ6枚(開花力43) 258 6327 ±0%
置物6枚 138 6327 ±0%

練習効果UP20%のキャラを6枚並べても、Σ258で足切りに届かない。 30%が必要。該当キャラは65体いるので現実的だが、まずここを埋めるのが最優先になる。

6. タッグを"発生させる"必要はない

これは直感に反するポイント。タッグボーナスは、タッグが発生していなくても効く。デッキに編成しているだけ、練習場所にいるだけで参照される。

同様に、モブの人数・やる気は経験点に一切影響しない

7. 彼女・サポ・相棒キャラは開花力では期待できない

該当127体のうち 120体(94%)が開花力23 で足切りに引っかかる。最高でも小嵐リョウの64。Σ開花力を稼ぐ枠としては数えられない。

ただし、Σ開花力284の足切りを超えられないデッキ(=キャラが揃っていない序盤)なら、どうせベースは下限に張り付いたままなので、体力回復要員として使うのはアリかもしれない

※ 筆者はこの構成でサクセスを回していないため、使用感は未確認。あくまで理屈上の話。


付録1:開花力の早見表

数値はすべて Lv50時のもの。セル内の名前は、そこに位置する実在キャラ。

タッグ \ 練効UP 10以下 15 20 25 30 35 40 45
150以下 23
(175体)
33 43
(36体)
54 64
(53体)
74
ゼルヴィー・ハイゼンベルク
フェルン
85
海野朋
白霧凍子
高原曲
95
イチロー
160 28 41 54
[白塵]白霧凍子
67 80
初白百合
大桜剛
朝顔かえで
93 106 119
180 40 59 77 95 113 151
ゼルヴィー※
150 168
200 52 76 99 123 163
大西※
170 194 217
220 64 93 122 151 180
泡瀬満里南
208 237 266
240 76
大谷翔平
110 144 178 213 247 281 315

※ [満開ステップ]ゼルヴィーは実際にはタッグ190、[超攻型]大西はタッグ210。近い行に置いている。

運営はトレードオフに調整している

実在するキャラは左下〜右上の対角線上に並ぶ。 右下(両方最高)は空っぽだ。

条件 該当数
タッグ150超(左の足切りを超える) 28体(9%)
練習効果UP10超(右の足切りを超える) 108体(36%)
両方超える わずか8体(2.6%)

その8体がこれ。

キャラ タッグ 練効UP 開花力
[水着]泡瀬満里南 220 30 180
[超攻型]大西 210 30 163
[満開ステップ]ゼルヴィー 190 35 151
初白百合 160 30 80
大桜剛 160 30 80
朝顔かえで 160 30 80
向井太陽 170 20 66
[白塵の魔女]白霧凍子 160 20 54

上位3体だけが頭一つ抜けている。 これが彼らが別格である理由になる。


付録2:開花力ランキング(Lv50)

全779体のイベキャラから、得意練習に球速・コントロール・スタミナ・変化球を含む302体ゼルヴィー・ハイゼンベルク(投手キャラ・得意練習メンタル)の計303体を対象とした。

開花力70以上(13体)

キャラ 得意練習 種別 タッグ 練効UP 開花力
[水着]泡瀬満里南 スタミナ/メンタル 投手 220 30 180
[超攻型]大西 球速/スタミナ 投手 210 30 163
[満開ステップ]ゼルヴィー コントロール/メンタル 投手 190 35 151
[伝説の始まり]イチロー コントロール/打撃 投手/野手 100 45 95
[ピクニック]高原曲 スタミナ/打撃 投手/野手 100 40 85
海野朋 変化球/メンタル 投手 100 40 85
白霧凍子 球速/変化球 投手 80 40 85
初白百合 コントロール/走塁 投手/野手 160 30 80
大桜剛 球速 投手 160 30 80
朝顔かえで 変化球 投手 160 30 80
[復活の二刀流]大谷翔平 変化球/筋力 投手/野手 240 0 76
ゼルヴィー・ハイゼンベルク メンタル 投手 100 35 74
フェルン コントロール/肩力 投手/野手 120 35 74

それ以下の層

開花力 体数 中身
66 1体 向井太陽(タッグ170・練効20)
64 53体 練効30・タッグ150以下。実戦デッキの主力
43 36体 練効20・タッグ150以下
24〜42 22体
23 175体 置物(タッグ150以下 かつ 練効10以下)

練習効果UPの分布(対象303体)

練効UP 体数
45% 1体
40% 3体
35% 3体
30% 58体
25% 1体
20% 38体
15% 4体
10% 38体
5% 2体
0% 155体

練習効果UP30%以上が65体。 ここを6枚集めればΣ開花力384で足切りを超えられる。

データ出典:GameWith「全キャラ絞り込み検索ツール」のタッグボーナス・練習効果UPの値(Lv50時)。この値はゲーム内のデッキ編成画面と一致する。 wikiによっては上限解放なしの基礎テーブル値を載せている場合があり、そちらを使うと計算が合わないので注意。


注意書き

  • ベースの下限値 6327 は筆者の測定条件(特定の練習・練習Lv・経験点の種類)での値。条件が変われば下限も変わる。「6327」という数字自体は他の条件に流用できない
  • 足切りライン 284 は、実測で挟めているのは 240〜344 の範囲。この範囲内で外挿した推定値
  • 野手キャラには開花力に下降補正がかかるという情報がある(筆者未検証)。本記事のランキングは補正を考慮していない
  • 経験点は小数点処理の関係で数点ずれることがある
  • 投手育成で検証した。野手でも同じ式が成立するかは未確認

→ 実測データと検証手順は「検証編」へ

ロマン開花学園の練習経験点、どうやって計算式を割り出したか【検証編】 - こきず

ABC357 python Atcoderの記録

問題はこちら
3完

A, B, C

##################### A
N, M = list(map(int, input().split()))
H = list(map(int, input().split()))
counter = 0
for hand in H:
    M -= hand
    if M>=0:
        counter+=1
print(counter)
##################### B
S = input()

def count_upper_lower(string):
    upper_count = sum(1 for char in string if char.isupper())
    lower_count = sum(1 for char in string if char.islower())
    return upper_count, lower_count
upper_count, lower_count = count_upper_lower(S)
if upper_count > lower_count:
    print(S.upper())
else:
    print(S.lower())

##################### C
import pandas as pd
N = int(input())
carpet ={0 : pd.DataFrame([["#"]])}
i = 1
while i < 7:
    center_grid = pd.DataFrame([["." for x in range(3**(i-1))] for y in range(3**(i-1))])
    # print(center_grid)
    carpet_i = pd.concat(
        [pd.concat([carpet[i-1], carpet[i-1], carpet[i-1],], axis = 1, ignore_index=True),
        pd.concat([carpet[i-1], center_grid, carpet[i-1],], axis = 1, ignore_index=True),
        pd.concat([carpet[i-1], carpet[i-1], carpet[i-1],], axis = 1, ignore_index=True)],
        axis = 0,
        ignore_index=True
    )
    carpet[i] = carpet_i
    i+=1

# DataFrameを指定された形式で出力する関数
def print_as_specified_format(df):
    output = ''
    for row in df.values:
        output += ''.join(row) + '\n'
    print(output)

print_as_specified_format(carpet[N])


D
GPTに聞いた考え方
1.VNは下記のように式変形できるが、分数の形であるためmodを計算しにくい。
そこでどうにかして分母を別の形で表せないか考える。

2.分母をー1乗の形に変換

分母をー1乗の形に変換

3. P-2乗の形に変換
P-2乗の形に変換

4. 最終的にこのように変換できる
最終的にこのように変換できる

5. 各()ごとにmodを求める。 10のKN乗などは非常に大きくなる可能性があるが、繰り返し2乗法で高速に処理できる
以下GPTによる説明コピペ--------------------------------------------------------------- 問題の数式を (P) で割った余りを求めるために、次の式に注目します:

[ (10^{KN} - 1) \cdot (10K - 1)^{P-2} \pmod{P} ]

この式を評価する際には、次の各部分の余りを計算します:

  1. (10^{KN} - 1 \mod P)
  2. (10K - 1 \mod P)
  3. ((10K - 1)^{P-2} \mod P)
  4. 最終的にこれらを掛け合わせた結果の (\mod P)

それぞれの部分を順に説明します。

ステップ 1: (10^{KN} - 1 \mod P) の計算

  1. まず (10^{KN} \mod P) を計算します。これは、通常のべき乗を計算するのではなく、繰り返し二乗法を用いて効率的に計算します。
  2. 次に、そこから 1 を引いた結果の余りを求めます。

[ 10^{KN} \mod P \quad \text{を求め、その後} \quad 10^{KN} - 1 \mod P ]

ステップ 2: (10K - 1 \mod P) の計算

  1. (10K \mod P) を同様に繰り返し二乗法を使って計算します。
  2. そこから 1 を引いた結果の余りを求めます。

[ 10K \mod P \quad \text{を求め、その後} \quad 10K - 1 \mod P ]

ステップ 3: ((10K - 1)^{P-2} \mod P) の計算

  1. ステップ 2で計算した (10K - 1 \mod P) の結果を基に、フェルマーの小定理を使ってその逆元を求めます。
  2. フェルマーの小定理によれば、(a^{P-1} \equiv 1 \pmod{P}) から、(a^{P-2} \equiv a^{-1} \pmod{P}) が得られます。
  3. ここで、(a = 10K - 1) として、その逆元を繰り返し二乗法を使って計算します。

[ (10K - 1)^{P-2} \mod P ]

ステップ 4: 最終的な余りの計算

  1. ステップ 1で求めた ((10^{KN} - 1) \mod P) の値と、ステップ 3で求めた逆元の値 ((10K - 1)^{P-2} \mod P) を掛け合わせ、その結果の余りを求めます。

[ (10^{KN} - 1) \cdot (10K - 1)^{P-2} \mod P ]

コードによる実装

以下に、上記の手順をPythonコードで実装します:

def mod_exp(base, exp, mod):
    result = 1
    base = base % mod
    while exp > 0:
        if (exp % 2) == 1:
            result = (result * base) % mod
        exp = exp >> 1
        base = (base * base) % mod
    return result

def mod_inverse(a, p):
    # フェルマーの小定理により逆元を計算
    return mod_exp(a, p - 2, p)

def find_remainder(K, N, P):
    # Step 1: 10^(KN) - 1 % P
    a_KN = mod_exp(10, K * N, P)
    numerator = (a_KN - 1) % P
    
    # Step 2: 10^K - 1 % P
    a_K = mod_exp(10, K, P)
    denominator = (a_K - 1) % P
    
    # Step 3: 逆元の計算
    denominator_inv = mod_inverse(denominator, P)
    
    # Step 4: 最終的な余りの計算
    result = (numerator * denominator_inv) % P
    return result

# 使用例
K = 3
N = 4
P = 1000000007

remainder = find_remainder(K, N, P)
print(remainder)

各ステップのまとめ

  1. Step 1: (10^{KN} \mod P) を計算し、そこから 1 を引いて余りを求める。
  2. Step 2: (10K \mod P) を計算し、そこから 1 を引いて余りを求める。
  3. Step 3: ステップ 2で求めた値の逆元をフェルマーの小定理を使って計算する。
  4. Step 4: ステップ 1の結果とステップ 3の逆元を掛け合わせ、その余りを求める。

この方法により、効率的に与えられた数式の余りを求めることができます。
GPTによる説明コピペ-ここまで--------------------------------------------------------------

N = input()
len_N = len(N)
n = int(N)
M = 998244353
# print(len_N,n,N)
def power_mod(K, n, M):
    result = 1
    K %= M  # KをMで割った余りを計算
    while n > 0:
        if n % 2 == 1:
            result = (result * K) % M
        n //= 2
        K = (K * K) % M
    return result

def calculate_modular_expression(K, n, M):
    if K % M == 1:
        return (n + 1) % M
    else:
        return ((power_mod(K, n , M) - 1) * pow(K - 1, -1, M)) % M

# # 例
# K = 5
# n = 3
# M = 13
print(((n % M) * calculate_modular_expression(10**len_N, n, M)) % M)  # (K**(n+1) - 1)/(K-1)をMで割った余りを出力


E





F





ARC176 python Atcoderの記録

問題はこちら


A

N, M = list(map(int, input().split()))
print(N*M) # 1の個数はN*M個
"""
考え方
M=1で自由に1を置けるとき:対角線すべてのマスに1を置くのが最もシンプル。
M=1で置く場所を決められたとき:そのマスから対角線と平行なマスに1を置くのが最もシンプル。
M=M'で置く場所を決められたとき:そのマスから対角線と平行なマスに1を置くことをM回行う。マスが重複した場合、自由に選んでいい感じに1を置く。

実装
1を置くマスごとに、斜めのマスを出力する。
1を置いた斜めのラインを管理しておき、重複した数に応じて、まだ1を置いていない斜めのラインに1を置く。
斜めラインの命名は1列目のマスで何行目に1を置くかで行う。(対角線は1、対角線の下のラインだと2, ... N)
"""
diagonal_lines = set()
# 指定されたマスを通る斜めラインの出力
for m in range(M):
    A,B= list(map(int, input().split()))
    diagonal_line = (A-B+1)%N
    if diagonal_line == 0:
        diagonal_line = N
    if diagonal_line in diagonal_lines: # 既に出力済みであれば、次のマスの操作へ。
        continue
    diagonal_lines.add(diagonal_line)
    for i in range(N):
        if (diagonal_line + i)%N == 0:
            temp = N
        else:
            temp = (diagonal_line + i)%N
        print(temp, 1 + i)
# 不足分の斜めラインの出力
counter = M - len(diagonal_lines)
for s in range(1,N+1):
    if counter == 0: # 斜めラインをM個出力していればBreak
        break
    if s in diagonal_lines: # 既に出力済みであれば、次のマスの操作へ。
        continue
    diagonal_lines.add(s)
    counter  -= 1
    for i in range(N):
        if (s + i)%N == 0:
            temp = N
        else:
            temp = (s + i)%N
        print(temp, 1 + i)
    


B
N>Mばかり考えており時間切れ





C





D





E





F





ABC350 python Atcoderの記録

問題はこちら


A

S = input()
T = int(S[-3:])
flag = "No"
if 1<= T <= 315 or 317 <= T <= 349:
    flag = "Yes" 
print(flag) 


B

N,Q = list(map(int, input().split()))
T = list(map(int, input().split()))
teeth = [0] + [1 for _ in range(N)] # 1-indexed
for t in T:
    if teeth[t] == 1:
        teeth[t] = 0
    else:
        teeth[t] = 1
print(sum(teeth))


C

N = int(input())
A = [0] + list(map(int, input().split()))
output = []
K = 0
while A != list(range(N+1)):
    for i in range(1, N):
        if A[i] != i:
            output.append([min(i,A[i]), max(i,A[i])])
            A[A[i]], A[i] = A[i], A[A[i]]
            
            K += 1
print(K)
for l in output:
    print(*l)
# print(A)


D
Union-Findを使えばよいらしい。 要復習

zenn.dev

N, M = list(map(int, input().split()))

class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))
        self.rank = [0] * n
        self.size = [1] * n  # 各要素が属する部分木の要素数

    def find(self, x):
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]

    def union(self, x, y):
        root_x = self.find(x)
        root_y = self.find(y)
        if root_x == root_y:
            return False
        if self.rank[root_x] < self.rank[root_y]:
            self.parent[root_x] = root_y
            self.size[root_y] += self.size[root_x]
        elif self.rank[root_x] > self.rank[root_y]:
            self.parent[root_y] = root_x
            self.size[root_x] += self.size[root_y]
        else:
            self.parent[root_y] = root_x
            self.rank[root_x] += 1
            self.size[root_x] += self.size[root_y]
        return True

    def get_size(self, x):
        root = self.find(x)
        return self.size[root]

uf = UnionFind(N)

for _ in range(M):
    A, B = list(map(int, input().split()))
    A, B = A - 1, B - 1  # 0-indexedに修正
    uf.union(A, B)
    
# 最終的な根を求める
roots = set()
for i in range(N):
    roots.add(uf.find(i))
    
# 根から部分木の要素数を求める
max_edges = 0
for root in roots:
    n = uf.get_size(root)
    max_edges += n * (n - 1) // 2  # 整数の除算
# 現在の辺の数を引いて答えを算出
print(max_edges - M)


E





F





ARC175 python Atcoderの記録

問題はこちら
1完

A
くそ汚いコード。後で書き直したい。

N = int(input())
P = ["-"] + list(map(int, input().split()))
S = "-" + input()
"""
結局みんな右で取るor左で取るを合わせる必要がある。
dp[i]: P[i-1]の人までスプーンをとった時の聞き手の組み合わせ=Sの有り得方
dpの遷移(右側をとることが確定しているとき) 
dp[i] = dp[i-1] *2 if S[P[i]]が両方を選べるとき→スプーンが右側にしかなく、?の時→S[P[i]]が?で、i+1のスプーンしかないとき
dp[i] = dp[i-1]  if P[i]がどちらかを選べるとき→S[P[i]]がLかRで、i+1のスプーンしかない。または→S[P[i]]がRで、両方のスプーンがある。
dp[i] = 0 P[i]が右のスプーンを選べないとき→S[P[i]]がLで、両方のスプーンがあるときor スプーンがない
"""
MOD = 998244353
# 右のスプーンをとるときのdp
dp_R = [1]
spoon = [[] for _ in range(N+1)]
for i in range(N+1):
    spoon[i] = ["L", "R"] if i != 0 else []

for i in range(1,N+1):
    if (S[P[i]] == "L" and spoon[P[i]] == ["L", "R"]) or (spoon[P[i]] ==["L"]) or (spoon[P[i]] ==[]):
        dp_R.append(0)
        break
    elif S[P[i]] == "?" and spoon[P[i]] == ["R"]:
        dp_R.append(dp_R[-1] *2 % MOD)
        spoon[P[i]] = []
        index = P[i] + 1
        if index == N+1:
            result = spoon[1].remove("L")
        else:
            result = spoon[index].remove("L")

    else:
        if spoon[P[i]] == ["L", "R"]:
            dp_R.append(dp_R[-1])
            spoon[P[i]] = ["L"]
            index = P[i] + 1
            if index == N+1:
                result = spoon[1].remove("L")
            else:
                result = spoon[index].remove("L")

        elif spoon[P[i]] == ["R"]:
            dp_R.append(dp_R[-1])
            spoon[P[i]] = []
            index = P[i] + 1
            if index == N+1:
                result = spoon[1].remove("L")
            else:
                result = spoon[index].remove("L")
# 左のスプーンをとるときのdp
dp_L = [1]
spoon = [[] for _ in range(N+1)]
for i in range(N+1):
    spoon[i] = ["L", "R"] if i != 0 else []

for i in range(1,N+1):
    if (S[P[i]] == "R" and spoon[P[i]] == ["L", "R"]) or (spoon[P[i]] ==["R"]) or (spoon[P[i]] ==[]):
        dp_L.append(0)
        break
    elif S[P[i]] == "?" and spoon[P[i]] == ["L"]:
        dp_L.append(dp_L[-1] *2 % MOD)
        spoon[P[i]] = []
        index = P[i] - 1
        if index == 0:
            result = spoon[N].remove("R")
        else:
            result = spoon[index].remove("R")

    else:
        if spoon[P[i]] == ["L", "R"]:
            dp_L.append(dp_L[-1])
            spoon[P[i]] = ["R"]
            index = P[i] - 1
            if index == 0:
                result = spoon[N].remove("R")
            else:
                result = spoon[index].remove("R")
        elif spoon[P[i]] == ["L"]:
            dp_L.append(dp_L[-1])
            spoon[P[i]] = []
            index = P[i] - 1
            if index == 0:
                result = spoon[N].remove("R")
            else:
                result = spoon[index].remove("R")

print((dp_R[-1] + dp_L[-1])%MOD)


B
解説AC
交換したときに累積和が最大で2増加することに気づかなかった。

N, A, B = list(map(int, input().split()))
S = input()
# (なら+1、)なら-1として累積和と途中の最小値を計算。累積和//2が置換の必要数
# またリストのほうが後で都合がよいのでリストに格納
list_S = []
min_count =  float('inf')
fin_count = 0
for s in S:
    if s == "(":
        fin_count += 1
    if s == ")":
        fin_count -= 1
    min_count = min(min_count, fin_count)
    list_S.append(s)
# print(min_count, fin_count)

# 置換のコストを求める
cost = (abs(fin_count)//2)*B
# 置換後のSを考える
if fin_count > 0:
    swap_count = 0
    for i in range(len(list_S)-1,-1,-1):
        if list_S[i] == "(":
            list_S[i] = ")"
            swap_count += 1
            if swap_count >= abs(fin_count)//2:
                break
if fin_count < 0:
    swap_count = 0
    for i in range(len(list_S)):
        if list_S[i] == ")":
            list_S[i] = "("
            swap_count += 1
            if swap_count >= abs(fin_count)//2:
                break
# print(cost)
# もう一度累積和をとって交換の必要回数を求める
min_count = 0
fin_count = 0
for s in list_S:
    if s == "(":
        fin_count += 1
    if s == ")":
        fin_count -= 1
    min_count = min(min_count, fin_count)
# 交換のコストを求める。1交換すると最大で累積和が+2されることに注意
if min_count < 0:
    cost += (abs(min_count)+1)//2 * min(A, 2*B)
print(cost)


C





D





E





F