├── .clang-format ├── .github └── workflows │ └── verify.yml ├── .gitignore ├── .verify-helper ├── config.toml ├── docs │ ├── _config.yml │ └── index.md └── timestamps.remote.json ├── LICENSE ├── Makefile ├── README.md ├── build ├── base.css ├── build.js ├── hash.sh ├── notebook.css └── notebook.html ├── docs ├── FPS │ ├── FFT.md │ └── FFT_fast.md ├── data-structure │ ├── BIT.md │ └── FastSet.md ├── extra │ └── modint_fast.md ├── math │ ├── BinaryGCD.md │ └── ExtGCD.md ├── modint │ ├── BarrettReduction.md │ └── modint.md └── string │ ├── KMP.md │ ├── Manacher.md │ ├── RollingHash.md │ ├── SuffixArray.md │ └── Zalgorithm.md ├── notebook.pdf ├── package-lock.json ├── package.json ├── requirements.txt ├── src ├── FPS │ ├── FFT.hpp │ ├── linear-recurrence.hpp │ ├── poly.hpp │ └── relaxed-convolution.hpp ├── data-structure │ ├── BIT.hpp │ ├── FastSet.hpp │ ├── Skew-Heap.hpp │ ├── cht.hpp │ ├── hash_map.hpp │ ├── lazy-segtree.hpp │ ├── li-chao.hpp │ ├── line_container.hpp │ ├── link-cut.hpp │ ├── pbds.hpp │ ├── rbst.hpp │ ├── segbeats.hpp │ ├── segtree-2d.hpp │ ├── segtree.hpp │ ├── sparse-table-disjoint.hpp │ ├── swag.hpp │ └── wavelet_matrix.hpp ├── dp │ ├── d-edge-monge.hpp │ ├── mo-rollback.hpp │ ├── mo.hpp │ ├── monge-incremental-rowmin.hpp │ └── monotone-minima.hpp ├── flow │ ├── bipartite-matching.hpp │ ├── flow.hpp │ ├── lower-upper-bound-flow.hpp │ ├── mcf.hpp │ ├── 二部グラフ.md │ └── 燃やす埋める.md ├── geometry │ ├── argument-sort.hpp │ ├── circle.hpp │ ├── convex-hull.hpp │ ├── funcs.hpp │ └── line.hpp ├── graph │ ├── bcc.hpp │ ├── eulerian-trail.hpp │ ├── lowlink.hpp │ ├── max_matching.hpp │ ├── maximum-independent-set.hpp │ ├── scc.hpp │ └── tecc.hpp ├── math │ ├── ExtGCD.hpp │ ├── and-or-convolution.hpp │ ├── binom.hpp │ ├── crt.hpp │ ├── floor_sum.hpp │ ├── lagrange-hokan.hpp │ ├── matrix.hpp │ ├── prime.hpp │ ├── primitive-root.hpp │ └── xor-convolution.hpp ├── memo │ ├── Primes.md │ └── math.md ├── misc │ ├── clock.hpp │ └── simplex.hpp ├── modint │ ├── BarrettReduction.hpp │ └── modint.hpp ├── string │ ├── KMP.hpp │ ├── Manacher.hpp │ ├── RollingHash.hpp │ ├── SuffixArray.hpp │ ├── Zalgorithm.hpp │ └── enumerate-runs.hpp ├── template │ ├── 0settings.sh │ ├── 1template.hpp │ ├── hash.sh │ ├── random_test.sh │ └── rnd.hpp └── tree │ ├── block-cut-tree.hpp │ └── hld.hpp └── test ├── FPS ├── FFT.test.cpp └── FFT_fast.test.cpp ├── benchmark ├── FFT.cpp ├── FastSet.cpp └── SuffixArray.cpp ├── data-structure ├── BIT.test.cpp └── FastSet.test.cpp ├── math ├── BinaryGCD.test.cpp └── ExtGCD.test.cpp ├── modint ├── BarrettReduction.test.cpp └── modint.test.cpp ├── string ├── KMP.test.cpp ├── LCP.test.cpp ├── Manacher.test.cpp ├── RollingHash.test.cpp ├── SuffixArray.test.cpp └── Zalgorithm.test.cpp ├── template.hpp └── template.test.cpp /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Chromium 2 | AccessModifierOffset: -4 3 | AllowAllArgumentsOnNextLine: true 4 | AllowAllConstructorInitializersOnNextLine: true 5 | AllowAllParametersOfDeclarationOnNextLine: true 6 | AllowShortBlocksOnASingleLine: Always 7 | AllowShortCaseLabelsOnASingleLine: true 8 | AllowShortEnumsOnASingleLine: true 9 | AllowShortFunctionsOnASingleLine: All 10 | AllowShortIfStatementsOnASingleLine: AllIfsAndElse 11 | AllowShortLambdasOnASingleLine: All 12 | AllowShortLoopsOnASingleLine: true 13 | AlwaysBreakTemplateDeclarations: No 14 | BreakBeforeBinaryOperators: NonAssignment 15 | ColumnLimit: 120 16 | IndentWidth: 3 17 | IndentWrappedFunctionNames: true 18 | SpaceAfterTemplateKeyword: false 19 | SpaceBeforeParens: Never 20 | SortIncludes: Never 21 | -------------------------------------------------------------------------------- /.github/workflows/verify.yml: -------------------------------------------------------------------------------- 1 | name: Verify library & Generate documentation 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | jobs: 10 | verify: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v4 15 | with: 16 | fetch-depth: 0 17 | 18 | - name: Set up Python 19 | uses: actions/setup-python@v5 20 | with: 21 | python-version: '3.x' 22 | cache: 'pip' 23 | 24 | - name: Install dependencies 25 | run: | 26 | pip install -U pip 27 | pip install -r requirements.txt 28 | 29 | - run: oj-verify all 30 | env: 31 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 32 | GH_PAT: this_token_is_never_used_but_oj_verify_requires_this 33 | 34 | - run: git switch main 35 | 36 | - name: Set up Node.js 37 | uses: actions/setup-node@v4 38 | with: 39 | node-version: 'latest' 40 | cache: 'npm' 41 | 42 | - name: Install Vivliostyle 43 | run: npm install -g @vivliostyle/cli clang-format 44 | 45 | - name: Install dependencies 46 | run: npm install 47 | 48 | - name: Build PDF 49 | run: make build 50 | 51 | - name: commit PDF 52 | run: git add . && git commit -m "[skip actions] build PDF" && git push 53 | 54 | - name: copy to gh-pages 55 | run: | 56 | DIR=$(mktemp -d) 57 | cp notebook.pdf $DIR 58 | cp build/*.css $DIR 59 | cp build/*.html $DIR 60 | git clean -dfx 61 | git switch gh-pages 62 | cp $DIR/* . 63 | git add . && git commit -m "build PDF" && git push 64 | git switch main 65 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .DS_Store 3 | .vscode/ 4 | .verify-helper/docs/static/base.css 5 | .verify-helper/docs/static/notebook.css 6 | .verify-helper/docs/static/notebook.html 7 | .verify-helper/docs/static/notebook.pdf 8 | -------------------------------------------------------------------------------- /.verify-helper/config.toml: -------------------------------------------------------------------------------- 1 | [[languages.cpp.environments]] 2 | CXX = "g++" 3 | CXXFLAGS = ["-std=c++20", "-Wall", "-Wextra", "-Wshadow", "-O2"] 4 | -------------------------------------------------------------------------------- /.verify-helper/docs/_config.yml: -------------------------------------------------------------------------------- 1 | 2 | # generated by build/build.js 3 | title: 'ICPC Notebook' 4 | exclude: ['node_modules', 'test/benchmark'] 5 | -------------------------------------------------------------------------------- /.verify-helper/docs/index.md: -------------------------------------------------------------------------------- 1 | みんなでつくる最強の ICPC 用ライブラリ (予定) 2 | 3 | - [ライブラリをまとめたページ](notebook.html) 4 | - [ライブラリをまとめた PDF](notebook.pdf) 5 | 6 | ### 前提要件 7 | 8 | - C++20 9 | - GCC 11 以上 10 | -------------------------------------------------------------------------------- /.verify-helper/timestamps.remote.json: -------------------------------------------------------------------------------- 1 | { 2 | "test/math/ExtGCD.test.cpp": "2024-09-04 19:36:22 +0900", 3 | "test/string/KMP.test.cpp": "2024-09-04 19:36:22 +0900", 4 | "test/string/Manacher.test.cpp": "2024-09-04 19:36:22 +0900", 5 | "test/template.test.cpp": "2024-09-04 19:36:22 +0900" 6 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PHONY: build verify serve 2 | 3 | build: notebook.pdf 4 | 5 | verify: .verify-helper/timestamps.local.json $(wildcard src/*/* test/* test/*/*) 6 | clang-format -i test/*/*.cpp test/*.hpp 7 | oj-verify run 8 | 9 | URL = "http://127.0.0.1:4000" 10 | 11 | serve: build verify 12 | cp notebook.pdf .verify-helper/docs/static/ 13 | cp build/notebook.html .verify-helper/docs/static/ 14 | cp build/*.css .verify-helper/docs/static/ 15 | oj-verify docs 16 | cd .verify-helper/markdown; \ 17 | bundle install; \ 18 | ( sleep 5.5; \ 19 | ( command -v open && open $(URL) ) || \ 20 | ( command -v start && start $(URL) ) || \ 21 | xdg-open $(URL) ) & \ 22 | bundle exec jekyll serve --incremental 23 | 24 | notebook.pdf: build/base.css build/notebook.css build/notebook.html 25 | vivliostyle build build/notebook.html -o notebook.pdf 26 | 27 | build/notebook.html: build/build.js $(wildcard src/*/* src/*/*/*) .clang-format 28 | clang-format -i $(wildcard src/*/*.hpp src/*/*/*.hpp) 29 | node build/build.js 30 | 31 | build/notebook.css: build/build.js 32 | node build/build.js 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ICPC_notebook 2 | 3 | [![Actions Status](https://github.com/tatyam-prime/ICPC_notebook/workflows/verify/badge.svg)](https://github.com/tatyam-prime/ICPC_notebook/actions) [![GitHub Pages](https://img.shields.io/static/v1?label=GitHub+Pages&message=document+&color=brightgreen&logo=github)](https://tatyam-prime.github.io/ICPC_notebook/) 4 | 5 | https://github.com/tatyam-prime/ICPC_notebook?tab=readme-ov-file 6 | 7 | - CSS 組版で、ファイルを置くだけで PDF が簡単に作れる、ICPC 用ライブラリのすごいテンプレート 8 | - かつ、みんなでつくる最強の ICPC 用ライブラリ (予定) 9 | - [ライブラリのドキュメント](https://tatyam-prime.github.io/ICPC_notebook/) 10 | - [ライブラリをまとめた PDF](https://github.com/KentaroMatsushita/icpc_library/blob/main/notebook.pdf) 11 | 12 | ## private なコピーを作るには 13 | 14 | 1. 新規 private repository を作る 15 | 2. repository の Settings -> Actions -> Workflow permissions を Read and Write に設定 16 | 3. `git clone https://github.com/tatyam-prime/ICPC_notebook.git && cd ICPC_notebook` 17 | 4. `git remote set-url origin {your_private_repository_url}` 18 | 5. `git commit -m "test" --allow-empty && git push` 19 | 6. workflow が動くことを確認 20 | 7. [README.txt](README.txt) をいい感じに修正 21 | 22 | ## 内容を変更するには 23 | 24 | 1. [src/\*/\*](src/) の中身を変更する 25 | 2. [build/build.js](build/build.js) の設定項目を変更する 26 | 3. commit & push 27 | 28 | ## 手元で動かすには 29 | 30 | ### 事前にインストールするもの 31 | 32 | - node.js (v18 以上) 33 | - npm 34 | - `brew install node` / 35 | - clang-format 36 | - `brew install clang-format` / `sudo apt install clang-format` 37 | - vivliostyle 38 | - `npm install -g @vivliostyle/cli` 39 | - その他依存関係 40 | - `npm install` 41 | - (使うなら) oj-verify 42 | - `pip3 install online-judge-verify-helper` 43 | 44 | ### PDF を生成する 45 | 46 | 1. `make build` 47 | 48 | ### oj-verify で verify 49 | 50 | 1. `make verify` 51 | 52 | ### oj-verify ページを生成 53 | 54 | 1. `make serve` 55 | 56 | -------------------------------------------------------------------------------- /build/base.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@100..800&family=M+PLUS+1p&family=Ubuntu:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&display=swap&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap'); 2 | /* @import url("https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css"); */ 3 | @import url("https://cdnjs.cloudflare.com/ajax/libs/prism-themes/1.9.0/prism-coldark-cold.min.css"); 4 | 5 | 6 | html, 7 | code { 8 | font-family: 'JetBrains Mono', 'M PLUS 1p'; 9 | font-variant-ligatures: none; 10 | } 11 | 12 | pre { 13 | white-space: pre-wrap; 14 | margin: 0; 15 | } 16 | 17 | div.content { 18 | padding: 0.3em 0; 19 | border-top: 1px solid; 20 | border-bottom: 1px solid; 21 | } 22 | 23 | h1, 24 | h2, 25 | h3, 26 | h4, 27 | h5, 28 | h6 { 29 | margin-block-start: 0.2em; 30 | margin-block-end: 0.2em; 31 | padding-block-start: 0.3em; 32 | padding-block-end: 0.3em; 33 | break-after: avoid; 34 | } 35 | 36 | a { 37 | color: currentColor; 38 | } 39 | 40 | h1#title { 41 | font-weight: 800; 42 | } 43 | 44 | .section { 45 | background-color: #005a8e99; 46 | color: #ffffff; 47 | } 48 | 49 | h2.section { 50 | margin-left: -0.5mm; 51 | margin-right: -0.5mm; 52 | padding-left: 1.5mm; 53 | } 54 | 55 | div.filename { 56 | display: flex; 57 | justify-content: space-between; 58 | align-items: baseline; 59 | } 60 | 61 | /* 印刷時の設定 */ 62 | @media print { 63 | 64 | body { 65 | column-count: 2; 66 | column-rule: 1px solid; 67 | column-gap: 6mm; 68 | } 69 | 70 | @page { 71 | size: A4 portrait; 72 | margin: 8mm 2.5mm 2.5mm 2.5mm; 73 | 74 | /* ヘッダー */ 75 | @top-left { 76 | content: "tatyam/ICPC_notebook"; 77 | } 78 | 79 | @top-right { 80 | content: "Page " counter(page) " of " counter(pages); 81 | } 82 | } 83 | } 84 | 85 | /* 目次にページ数を付加する */ 86 | nav#toc ol { 87 | list-style: none; 88 | } 89 | 90 | nav#toc>ol { 91 | padding-left: 0; 92 | } 93 | 94 | nav#toc a { 95 | display: inline-flex; 96 | width: 100%; 97 | text-decoration: none; 98 | align-items: baseline; 99 | } 100 | 101 | nav#toc a.section { 102 | padding-left: 0.5em; 103 | } 104 | 105 | nav#toc>ol>ol>li>a::before { 106 | margin-left: 0.5em; 107 | margin-right: 0.5em; 108 | border-bottom: 1px dotted; 109 | content: ''; 110 | order: 1; 111 | flex: auto; 112 | } 113 | 114 | nav#toc>ol>ol>li>a::after { 115 | text-align: right; 116 | content: target-counter(attr(href), page); 117 | align-self: flex-end; 118 | flex: none; 119 | order: 2; 120 | } 121 | 122 | /* 表に罫線をつける */ 123 | table { 124 | border-spacing: 0; 125 | border-top: 1px solid lightgray; 126 | border-left: 1px solid lightgray; 127 | } 128 | td, th { 129 | border-bottom: 1px solid lightgray; 130 | border-right: 1px solid lightgray; 131 | padding: 4px; 132 | } 133 | 134 | /* シンタックスハイライトの色を調整 */ 135 | .token.attr-name, 136 | .token.boolean, 137 | .token.boolean.important, 138 | .token.number, 139 | .token.constant, 140 | .token.selector .token.attribute { 141 | color: #001575; 142 | } 143 | .content { 144 | break-before: avoid; 145 | } 146 | .content-md { 147 | font-family: 'Roboto', 'M PLUS 1p'; 148 | } 149 | -------------------------------------------------------------------------------- /build/build.js: -------------------------------------------------------------------------------- 1 | const title = "ICPC Notebook"; // タイトル (先頭に表示) 2 | const teamname = "Speed Star (The University of Tokyo)"; // チーム名 + 大学名 (各ページ左上に表示) 3 | const fontsize = "7.4pt"; // フォントサイズ 4 | const orientation = "portrait"; // portrait (縦長) / landscape (横長) 5 | const num_columns = 2; // 何段組みか 6 | const break_after_toc = "column"; // toc の後に : page (改ページする) / column (改段する) / auto (強制しない) 7 | const section_order = ["template", // 8 | "data-structure", "dp", "math","graph", // 9 | "modint", "FPS", "tree", "flow", "string","geometry","misc", "memo"]; // src/* のフォルダを読み出す順序 10 | 11 | 12 | 13 | const fs = require('fs'); 14 | const html_escape = require('escape-html'); 15 | const prism = require('prismjs'); 16 | const loadLanguages = require('prismjs/components/'); 17 | loadLanguages("c"); 18 | loadLanguages("cpp"); 19 | loadLanguages("python"); 20 | loadLanguages("sh"); 21 | const cp = require('child_process'); 22 | const marked = require('marked'); 23 | 24 | let codeContent = ""; 25 | let ToCContent = ""; 26 | 27 | // ファイルを開いて中身を取り出し、拡張子によって prism.js でパース & HTML エンコードを行う 28 | function addCode(folder, filename) { 29 | const text = fs.readFileSync(folder + "/" + filename).toString(); 30 | 31 | // タイトル行 32 | ToCContent += ` 33 |
  • ${filename}
  • `; 34 | codeContent += ` 35 |
    36 |

    ${filename}

    `; 37 | 38 | // C++ ならハッシュ値を計算 39 | if (filename.endsWith(".cpp") || filename.endsWith(".hpp")) { 40 | var text_hash = cp.execSync(`cat ${folder}/${filename} | sh build/hash.sh`); 41 | codeContent += ` 42 | md5: ${text_hash}`; 43 | } 44 | codeContent += ` 45 |
    `; 46 | 47 | const highlight_text = (function () { 48 | // .md ファイルは marked で HTML にコンパイル 49 | if (filename.endsWith(".md")) { 50 | return marked.marked(text, { gfm: true }); 51 | } 52 | // prism.js でパース & HTML エンコード 53 | if (filename.endsWith(".cpp") || filename.endsWith(".hpp")) { 54 | return prism.highlight(text, prism.languages.cpp, "cpp"); 55 | } 56 | if (filename.endsWith(".py")) { 57 | return prism.highlight(text, prism.languages.python, "python"); 58 | } 59 | if (filename.endsWith(".sh")) { 60 | return prism.highlight(text, prism.languages.sh, "sh"); 61 | } 62 | return html_escape(text); 63 | })(); 64 | 65 | codeContent += ` 66 |
    `; 67 | if (filename.endsWith(".md")) { 68 | codeContent += highlight_text; 69 | } else { 70 | codeContent += ` 71 |
    ${highlight_text}
    72 | `; 73 | } 74 | 75 | codeContent += '
    \n'; 76 | } 77 | 78 | for (const section of section_order) { 79 | ToCContent += ` 80 |
  • ${section}
  • 81 |
      `; 82 | codeContent += ` 83 |

      ${section}

      84 | `; 85 | 86 | const folder = "src/" + section; 87 | 88 | if (fs.existsSync(folder)) { 89 | // フォルダ内のファイルを読み込む 90 | for (const file of fs.readdirSync(folder)) { 91 | if (fs.statSync(folder + "/" + file).isFile()) { 92 | addCode(folder, file); 93 | } 94 | } 95 | } else { 96 | // フォルダが空だったら warning を出す 97 | console.warn(`Warning: ${folder} does not exist.`); 98 | } 99 | 100 | ToCContent += ` 101 |
    `; 102 | } 103 | 104 | // build/notebook.html を出力 105 | fs.writeFileSync("build/notebook.html", ` 106 | 107 | 108 | 109 | 110 | 111 | ${title} 112 | 113 | 120 | 121 | 122 | 123 | 124 | 125 | 126 |

    ${title}

    127 | 128 | 133 | 134 | ${codeContent} 135 | 136 | `); 137 | 138 | // build/notebook.css を出力 139 | fs.writeFileSync("build/notebook.css", `/* generated by build/build.js */ 140 | @import url("base.css"); 141 | 142 | html, 143 | code { 144 | font-size: ${fontsize}; 145 | } 146 | 147 | nav#toc { 148 | break-after: ${break_after_toc}; 149 | } 150 | 151 | @media print { 152 | body { 153 | column-count: ${num_columns}; 154 | } 155 | 156 | @page { 157 | size: A4 ${orientation}; 158 | 159 | /* ヘッダー */ 160 | @top-left { 161 | content: "${teamname}"; 162 | } 163 | } 164 | }`); 165 | 166 | // .verify-helper/docs/_config.yml を出力 167 | fs.writeFileSync(".verify-helper/docs/_config.yml", ` 168 | # generated by build/build.js 169 | title: '${title}' 170 | exclude: ['node_modules', 'test/benchmark'] 171 | `); 172 | -------------------------------------------------------------------------------- /build/hash.sh: -------------------------------------------------------------------------------- 1 | # 標準入力から C++ ファイルを受け取り、コメント・空白・改行を削除し、md5 でハッシュする 2 | g++ -dD -E -P -fpreprocessed - | tr -d '[:space:]' | md5sum | cut -c-6 3 | -------------------------------------------------------------------------------- /build/notebook.css: -------------------------------------------------------------------------------- 1 | /* generated by build/build.js */ 2 | @import url("base.css"); 3 | 4 | html, 5 | code { 6 | font-size: 7.4pt; 7 | } 8 | 9 | nav#toc { 10 | break-after: column; 11 | } 12 | 13 | @media print { 14 | body { 15 | column-count: 2; 16 | } 17 | 18 | @page { 19 | size: A4 portrait; 20 | 21 | /* ヘッダー */ 22 | @top-left { 23 | content: "Speed Star (The University of Tokyo)"; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /docs/FPS/FFT.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: FFT (高速フーリエ変換 / 畳み込み) 3 | documentation_of: //src/FPS/FFT.hpp 4 | --- 5 | - 参考実装:[gifted infants](https://yosupo.hatenablog.com/entry/2019/07/02/122433) 6 | 7 | ## Depends on 8 | 9 | - [Modint](../modint/modint.hpp) 10 | 11 | ## 使い方 12 | 13 | - `void fft(vector& a)`:長さが $n$ : $2$ べきの数列 $a$ の離散フーリエ変換を行う. 14 | - $f(x) := a[0] + a[1]x + \dots + a[n - 1]x^{n - 1},\ \omega := e^{i\frac{\tau}{n}}$ としたとき,列 $[f(\omega^0), f(\omega^1), \dots, f(\omega^{n-1})]$ を返す. 15 | - **bit reversal 順ではないことに注意** 16 | - `vector conv(vector a, vector b)`:数列 $a, b$ の畳み込みを行う. 17 | - $c[k] := \sum_{i + j = k}a[i] \times b[j]$ で定義される,長さ $\text{sz}(a) + \text{sz}(b) - 1$ の数列 $c$ を返す. 18 | 19 | $O(n \log n)$ 時間 20 | 21 | ## 注意 22 | 23 | - `fft()` の入力は長さが 2 べきであること 24 | - **IFFT は,FFT における $[\omega^1, \dots, \omega^{n-1}]$ を $[\omega^{n-1}, \dots, \omega^{1}]$ で置き換えたものなので,FFT の結果の $[f(\omega^1), \dots, f(\omega^{n-1})]$ の部分を reverse すれば良い.出力を reverse する代わりに,入力の同じ部分を reverse しても良い.** 25 | - FFT → IFFT をすると各要素が $n$ 倍されるので、$n$ で割る必要がある 26 | 27 | ## ベンチマーク 28 | 29 | | $2^{20} + 2^{20}$ の畳み込み | 所要時間 | 30 | | --- | --- | 31 | | [簡易 modint](../modint/modint.hpp) + 簡易 FFT (これ) | 300 ms | 32 | | [32 bit で加減算をちゃんと書いた modint](../extra/modint_fast.hpp) + [bit reversal FFT](FFT_fast.hpp) | 123 ms | 33 | | [AC Library](https://github.com/atcoder/ac-library/blob/d8ca7f26686f6c78d15d13ca438ea866526e87fb/atcoder/convolution.hpp) | 79 ms | 34 | | [Nyaan さんの AVX2 FFT](https://nyaannyaan.github.io/library/verify/verify-yosupo-ntt/yosupo-convolution-ntt-avx2.test.cpp) | 43 ms | 35 | -------------------------------------------------------------------------------- /docs/FPS/FFT_fast.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: FFT (bit reversal ver.) 3 | documentation_of: //src/FPS/FFT_fast.hpp 4 | --- 5 | - 参考実装:[AC Library (初期実装)](https://github.com/atcoder/ac-library/blob/8250de484ae0ab597391db58040a602e0dc1a419/atcoder/convolution.hpp) 6 | 7 | ## Depends on 8 | 9 | - [Modint](../modint/modint.hpp) 10 | 11 | より高速な FFT.4 進でやるとより高速になるが,長すぎるので妥協 12 | 13 | ## 使い方 14 | 15 | - `void fft(vector& a)`:長さが $n$ : $2$ べきの数列 $a$ の離散フーリエ変換を行う 16 | - **`fft()` 後の配列は bit reversal 順になっていることに注意.**例えば $n = 16$ のとき,$(0101)_2 = 5$ の bit 順を反転させると $(1010)_2 = 10$ であるから,$f(\omega^5)$ の値は $a[10]$ に入っている. 17 | - `void ifft(vector& a)`:`fft()` の逆変換を行う 18 | - `vector conv(vector a, vector b)`:数列 $a, b$ の畳み込みを行う 19 | - $c[k] := \sum_{i + j = k}a[i] \times b[j]$ で定義される,長さ $\text{sz}(a) + \text{sz}(b) - 1$ の数列 $c$ を返す. 20 | 21 | $O(n \log n)$ 時間 22 | 23 | ## 注意 24 | 25 | - `fft()`, `ifft()` の入力は長さが 2 べきであること 26 | - FFT 後の配列は bit reversal 順に並ぶ 27 | - FFT → IFFT をすると各要素が $n$ 倍されるので、$n$ で割る必要がある 28 | -------------------------------------------------------------------------------- /docs/data-structure/BIT.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: BIT (Fenwick Tree) 3 | documentation_of: //src/data-structure/BIT.hpp 4 | --- 5 | 6 | - 参考実装:[AC Library](https://github.com/atcoder/ac-library/blob/8250de484ae0ab597391db58040a602e0dc1a419/atcoder/fenwicktree.hpp) 7 | 8 | ## 使い方 9 | 10 | 1 点加算・区間和ができるデータ構造 11 | 12 | - `BIT(ll n)`:長さ $n$ の配列を作る 13 | - `void add(ll i, ll x)`:`A[i] += x` を行う 14 | - `ll sum(ll r)`:`sum(A[:r])` を求める 15 | - `ll sum(ll l, ll r)`:`sum(A[l:r])` を求める 16 | 17 | 計算量 $O(\log n)$ / クエリ 18 | -------------------------------------------------------------------------------- /docs/data-structure/FastSet.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 高速 bitset (64 分木) 3 | documentation_of: //src/data-structure/FastSet.hpp 4 | --- 5 | 6 | - 参考実装:[Gifted Infants](https://yosupo.hatenablog.com/entry/2019/07/02/122433) 7 | 8 | ## 使い方 9 | 10 | 整数の set を高速化したい時に使う 11 | 12 | - `FastSet(ll n)`:長さ $n$ の bitset を作る 13 | - `void set(ll i)`:`A[i] = true` を行う 14 | - `void reset(ll i)`:`A[i] = false` を行う 15 | - `ll next(ll i)`:$i$ を超える最小の要素を求める 16 | - std::set における `A.upper_bound(i)` に相当 17 | - std::bitset における `A._Find_next(i)` に相当 18 | - `ll prev(ll i)`:$i$ より小さい最大の要素を求める 19 | - std::set における `prev(A.lower_bound(i))` に相当 20 | 21 | 時間計算量 $O(\log_{\text{word}} n)$ / クエリ 22 | 空間計算量 $(\frac{\text{word}}{\text{word} - 1}\cdot n + O(\log_{\text{word}} n))$ bits  ($\boldsymbol{n}$ bits くらいのメモリを使います) 23 | 24 | ## ベンチマーク 25 | 26 | 値域 $2^{30}$ 27 | 28 | | $n = 2^{20}$ 回の 追加 + next クエリ | 所要時間 | 29 | | std::set | 467 ms | 30 | | std::bitset | 254 ms | 31 | | FastSet | 56 ms | 32 | 33 | 脅威の 8 倍速! 34 | -------------------------------------------------------------------------------- /docs/extra/modint_fast.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 32 bit で加減算をちゃんと書いた Modint 3 | documentation_of: //src/extra/modint_fast.hpp 4 | --- 5 | 6 | modint の速度が欲しいときに使う 7 | PDF には含まれていません 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/math/BinaryGCD.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Binary GCD 3 | documentation_of: //src/math/BinaryGCD.hpp 4 | --- 5 | 6 | 割り算を使わない高速な GCD 7 | 8 | ## 使い方 9 | 10 | - `u64 binary_gcd(u64 x, u64 y)`:$x$ と $y$ の最大公約数を計算する. 11 | - $O(\log(x + y))$ 時間 12 | -------------------------------------------------------------------------------- /docs/math/ExtGCD.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 拡張ユークリッドの互除法 (Extended Euclidean algorithm) 3 | documentation_of: //src/math/ExtGCD.hpp 4 | --- 5 | - 参考実装:[KACTL](https://github.com/kth-competitive-programming/kactl/blob/main/content/number-theory/euclid.h) 6 | 7 | 割り算を使わない高速な GCD 8 | 9 | ## 使い方 10 | 11 | - `ll extgcd(ll a, ll b, ll& x, ll& y)`:$\text{gcd}(a, b)$ を返す.$(x, y)$ には,$ax + by = \text{gcd}(a, b)$ の整数解であって $\|x\| + \|y\|$ が最小のものが代入される. 12 | - $O(\log(x + y))$ 時間 13 | 14 | ## 使い方 (応用) 15 | 16 | - モジュロ逆元 `modinv(a, mod)` を求める:`extgcd(a, mod, x, y)` をすると `a * x + mod * y == 1` になるので,`x` が `a` のモジュロ逆元である. 17 | 18 | ## ソラ書きしてみよう 19 | 20 | $(1, 0, a)$ と $(0, 1, b)$ に対してユークリッドの互除法をするとできる. 21 | 22 | ```cpp 23 | array extgcd(ll a, ll b) { 24 | array A = {1, 0, a}, B = {0, 1, b}; 25 | while(B[2]) { 26 | ll q = A[2] / B[2]; 27 | rep(i, 0, 3) A[i] -= B[i] * q; 28 | swap(A, B); 29 | } 30 | return A; 31 | } 32 | ``` 33 | 34 | -------------------------------------------------------------------------------- /docs/modint/BarrettReduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Barrett Reduction 3 | documentation_of: //src/modint/BarrettReduction.hpp 4 | --- 5 | - 参考実装:[AC Library](https://github.com/atcoder/ac-library/blob/master/atcoder/internal_math.hpp) 6 | 7 | 同じ mod でたくさん計算するとき,剰余算を掛け算に変換して高速化する. 8 | 9 | ## 使い方 10 | 11 | - `Barrett br(mod)`:Barrett Reduction を準備する. 12 | - 制約:`mod < 2^32` 13 | - `u64 br.mul(u64 a, u64 b)`:`a * b % mod` を計算する. 14 | - 制約:`a * b < 2^64` 15 | 16 | ## 仕組み 17 | 18 | - 整数部 64 bit,小数部 64 bit の固定小数点数で商を計算する. 19 | - `im` には `1.0 / mod` の小数部 64 bit が書かれている. 20 | - `u64 x = ((__uint128_t)a * im) >> 64;` で商を計算している. 21 | 22 | ## 余談 23 | 24 | ジャッジが Ice Lake より前の Intel の CPU の場合,64 bit 除算が double 除算より 3 倍以上遅いことが知られている. 25 | あまりではなく商が欲しい場合,mod が固定ではない場合,もっと短く書きたい場合は,double 除算や long double 除算を書くと良い. 26 | -------------------------------------------------------------------------------- /docs/modint/modint.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Modint 3 | documentation_of: //src/modint/modint.hpp 4 | --- 5 | - 参考実装:[AC Library (初期実装)](https://github.com/atcoder/ac-library/blob/8250de484ae0ab597391db58040a602e0dc1a419/atcoder/convolution.hpp) 6 | 7 | - タイプ速度重視の簡易 modint 8 | - 速度が欲しいとき:[32 bit で加減算をちゃんと書いた Modint](../extra/modint_fast.hpp) 9 | - mod が素数でないとき:inv を [extgcd](../math/ExtGCD.hpp) にする 10 | - mod が実行時に決まり,これを高速化したいとき:[Barrett Reduction](./BarrettReduction.hpp) 11 | -------------------------------------------------------------------------------- /docs/string/KMP.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: KMP 法 (Knuth–Morris–Pratt algorithm) 3 | documentation_of: //src/string/KMP.hpp 4 | --- 5 | - 参考実装:[KACTL](https://github.com/kth-competitive-programming/kactl/blob/c52bac765cdd9cda1def052c698ffa7bd3318d29/content/strings/KMP.h) 6 | 7 | ## 使い方 8 | 9 | - `vector KMP(string s)`:$\text{kmp}[i] := \max\\{ l ≤ i \mid s[:l] = s[(i+1)-l:i+1] \\}$ で定義される配列 $\text{kmp}$ を求める 10 | 11 | $O(n)$ 時間 12 | -------------------------------------------------------------------------------- /docs/string/Manacher.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Manacher's algorithm 3 | documentation_of: //src/string/Manacher.hpp 4 | --- 5 | - 参考実装:[ei1333 (Luzhiled's memo)](https://ei1333.github.io/luzhiled/snippets/string/manacher.html) 6 | 7 | ## 使い方 8 | 9 | - `vector manacher(string s)`:文字列 $s$ の長さを $n$ として,長さ $n$ の整数列 $r$ を返す.$r[i]$ は $s[i]$ を中心とする回文半径で,$s[i - r[i]]$ から $s[i + r[i]]$ までが回文であることを表す. 10 | - 文字と文字の間を中心とする回文半径も知りたいときは,両端を含めた境界 ($N + 1$ 個) に適当な文字 1 種類を挿入しておく.返される値は,挿入前の文字列における回文直径${} + 1$ (すなわち,極大な回文の長さ${} + 1$) になる. 11 | 12 | $O(n)$ 時間 13 | -------------------------------------------------------------------------------- /docs/string/RollingHash.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Rolling Hash 3 | documentation_of: //src/string/RollingHash.hpp 4 | --- 5 | - 参考実装:[tatyam](https://github.com/tatyam-prime/kyopro_library/blob/master/RollingHash.cpp) 6 | 7 | ## 使い方 8 | 9 | - `RH rh(string s)`:文字列 $s$ に対する Rolling Hash を準備する 10 | - $O(n)$ 時間 11 | - `u64 rh.get(ll l, ll r)`:$s[l:r]$ の hash を求める 12 | - mod を $P := 2^{61}-1$ とし,基数 $r$ を $[0, P)$ からランダムに選ぶ 13 | - このとき,長さ $n$ の文字列 $s$ の hash は $(s[0] r^{n-1} + s[1] r^{n-2} + \dots + s[n-1] r^0) \bmod P$ で計算される 14 | - $O(1)$ 時間 15 | 16 | ## 使い方 (応用編) 17 | 18 | - LCP (Longest Common Prefix) を求めたいとき:LCP の長さを二分探索すれば,$O(\log n)$ 時間 / query 19 | - 文字列を辞書順で比較したいとき:LCP の長さを二分探索すれば,$O(\log n)$ 時間 / query 20 | 21 | ## 衝突確率 22 | 23 | - $2$ つの異なる長さ $n$ 以下の文字列が衝突する確率は $\frac{n}{P}$ 以下 24 | - 参考資料:[Schwartz–Zippel lemma による hash の解析 – noshi91](https://github.com/noshi91/blog/blob/master/pages/hash.pdf) 25 | - 相異なる $n$ 文字の文字列 $m$ 個がどこかで衝突する確率は,$\frac{n \cdot \binom{m}{2}}{P}$ 以下 26 | - $(n, m) = (1, 10^6)$ を $100$ ケースやっても $0.002\%$ なので,衝突は基本的に無視できる 27 | -------------------------------------------------------------------------------- /docs/string/SuffixArray.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Suffix Array 3 | documentation_of: //src/string/SuffixArray.hpp 4 | --- 5 | - 参考実装:[kactl](https://github.com/kth-competitive-programming/kactl/blob/431a6ef4ec6c04cf4c17e065089b7c4d451ea9cf/content/strings/SuffixArray.h) 6 | 7 | ## 使い方 8 | 9 | - `pair, vector> SA(string s)`:文字列 $s$ の Suffix Array と LCP Array の組を返す. 10 | - Suffix Array:`[0, 1, …, n-1].sort(key=(i => s[i:]))` 11 | - LCP Array:`lcp[i] = LCP(s[sa[i]:], s[sa[i+1]:])` 12 | - `lim` には $s$ の文字種の最大値を指定する 13 | - $O(n \log n)$ 時間 14 | 15 | ## ベンチマーク 16 | 17 | | $n = 2^{20}$ の SA + LCP | 所要時間 | 18 | | --- | --- | 19 | | これ | 310 ms | 20 | | [AC Library](https://github.com/atcoder/ac-library/blob/d8ca7f26686f6c78d15d13ca438ea866526e87fb/atcoder/string.hpp) | 100 ms | 21 | -------------------------------------------------------------------------------- /docs/string/Zalgorithm.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Z Algorithm 3 | documentation_of: //src/string/Zalgorithm.hpp 4 | --- 5 | - 参考実装:[KACTL](https://github.com/kth-competitive-programming/kactl/blob/c52bac765cdd9cda1def052c698ffa7bd3318d29/content/strings/KMP.h) 6 | 7 | ## 使い方 8 | 9 | - `vector Z(string s)`:$Z[i] := \text{LCP}(s, s[i:])$ で定義される配列 $Z$ を求める 10 | - $O(n)$ 時間 11 | 12 | ## 使い方 (応用編) 13 | 14 | - 文字列 $s$ の部分文字列に $t$ が現れるか判定:$\text{Z}(t + s)$ の後ろ $\text{sz}(s)$ 個に $\text{sz}(t)$ 以上があるか 15 | - 文字列 $s$ の最小周期:$\text{Z}(s + s)$ の $1$ 要素目以降で,はじめて $\text{sz}(s)$ 以上が出現する位置 16 | 17 | -------------------------------------------------------------------------------- /notebook.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KentaroMatsushita/icpc_library/610ef0cf2cb3aa7268fd45db9996f14d2064bbe5/notebook.pdf -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "icpc_library", 3 | "lockfileVersion": 2, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "dependencies": { 8 | "escape-html": "^1.0.3", 9 | "marked": "^12.0.0", 10 | "prismjs": "^1.29.0" 11 | } 12 | }, 13 | "node_modules/escape-html": { 14 | "version": "1.0.3", 15 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 16 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 17 | }, 18 | "node_modules/marked": { 19 | "version": "12.0.2", 20 | "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz", 21 | "integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==", 22 | "bin": { 23 | "marked": "bin/marked.js" 24 | }, 25 | "engines": { 26 | "node": ">= 18" 27 | } 28 | }, 29 | "node_modules/prismjs": { 30 | "version": "1.29.0", 31 | "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", 32 | "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", 33 | "engines": { 34 | "node": ">=6" 35 | } 36 | } 37 | }, 38 | "dependencies": { 39 | "escape-html": { 40 | "version": "1.0.3", 41 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 42 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 43 | }, 44 | "marked": { 45 | "version": "12.0.2", 46 | "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz", 47 | "integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==" 48 | }, 49 | "prismjs": { 50 | "version": "1.29.0", 51 | "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", 52 | "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==" 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "escape-html": "^1.0.3", 4 | "marked": "^12.0.0", 5 | "prismjs": "^1.29.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | online-judge-verify-helper 2 | -------------------------------------------------------------------------------- /src/FPS/FFT.hpp: -------------------------------------------------------------------------------- 1 | mint g = 3; // 原始根 2 | void fft(vm& a, bool inv = false) { 3 | int n = si(a), s = __lg(n); 4 | static vm z, iz; 5 | while(si(z) <= s) { 6 | z.eb(g.pow(mint(-1).x / (1 << si(z)))); 7 | iz.eb(z.back().inv()); 8 | } 9 | vm b(n); 10 | rep(i, 1, s + 1) { 11 | int w = 1 << s - i; 12 | mint base = inv ? iz[i] : z[i], now = 1; 13 | for(int y = 0; y < n / 2; y += w) { 14 | rep(x, w) { 15 | auto l = a[y << 1 | x], r = now * a[y << 1 | x | w]; 16 | b[y | x] = l + r, b[y | x | n >> 1] = l - r; 17 | } 18 | now *= base; 19 | } 20 | swap(a, b); 21 | } 22 | } 23 | 24 | vm mul(vm a, vm b) { 25 | int n = si(a), m = si(b); 26 | if(!n or !m) return {}; 27 | if(min(n, m) <= 30) { 28 | vm ans(n + m - 1); 29 | rep(i, n) rep(j, m) ans[i + j] += a[i] * b[j]; 30 | return ans; 31 | } 32 | int N = n + m - 1; 33 | int z = bit_ceil(unsigned(N)); 34 | a.resize(z), b.resize(z); 35 | fft(a), fft(b); 36 | rep(i, z) a[i] *= b[i]; 37 | fft(a, true); 38 | a.resize(n + m - 1); 39 | mint iz = mint(z).inv(); 40 | fore(e, a) e *= iz; 41 | return a; 42 | } 43 | -------------------------------------------------------------------------------- /src/FPS/linear-recurrence.hpp: -------------------------------------------------------------------------------- 1 | // [x ^ k] p / q 2 | mint LinearRecurrence(ll k, fps q, fps p) { 3 | q.shrink(); 4 | mint ret = 0; 5 | if(si(p) >= si(q)) { 6 | auto r = p / q; 7 | p -= r * q; 8 | p.shrink(); 9 | if(k < r.size()) ret += r[k]; 10 | } 11 | if(p.size() == 0) return ret; 12 | p.resize(q.size() - 1); 13 | while(k) { 14 | auto q2 = q; 15 | for(int i = 1; i < q2.size(); i += 2) q2[i] = -q2[i]; 16 | auto s = p * q2, t = q * q2; 17 | for(int i = (k & 1); i < s.size(); i += 2) p[i >> 1] = s[i]; 18 | for(int i = 0; i < t.size(); i += 2) q[i >> 1] = t[i]; 19 | k >>= 1; 20 | } 21 | return ret + p[0]; 22 | } 23 | // a * q = 0 24 | mint kitamasa(ll n, fps q, fps a) { 25 | if(n < si(a)) return a[n]; 26 | auto p = a.pre(si(q) - 1) * q; 27 | p.resize(si(q) - 1); 28 | return LinearRecurrence(n, q, p); 29 | } -------------------------------------------------------------------------------- /src/FPS/poly.hpp: -------------------------------------------------------------------------------- 1 | struct fps { 2 | vm v; 3 | fps(const vm& v = {}) : v(v) {} 4 | fps(int n) : v(n) {} 5 | void shrink() { 6 | while(v.size() && !v.back().x) v.pop_back(); 7 | } 8 | void resize(int n) { v.resize(n); } 9 | int size() const { return int(v.size()); } 10 | mint freq(int p) const { return (p < size()) ? v[p] : 0; } 11 | mint& operator[](int k) { return v[k]; } 12 | void emplace_back(mint x) { v.eb(x); } 13 | fps pre(int le) const { return {{v.begin(), v.begin() + min(size(), le)}}; } 14 | fps operator-() const { 15 | vm res{v}; 16 | fore(e, res) e = -e; 17 | return res; 18 | } 19 | fps operator+(const fps& r) const { 20 | auto n = max(size(), r.size()); 21 | vm res(n); 22 | rep(i, n) res[i] = freq(i) + r.freq(i); 23 | return res; 24 | } 25 | fps operator-(const fps& r) const { return (*this) + (-r); } 26 | fps operator*(const fps& r) const { return {mul(v, r.v)}; } 27 | fps operator*(const mint& r) const { 28 | int n = size(); 29 | vm res(n); 30 | for(int i = 0; i < n; i++) res[i] = v[i] * r; 31 | return res; 32 | } 33 | fps operator/(const mint& r) const { return *this * r.inv(); } 34 | fps operator/(const fps& r) const { 35 | if(size() < r.size()) return {{}}; 36 | int n = size() - r.size() + 1; 37 | return (rev().pre(n) * r.rev().inv(n)).pre(n).rev(); 38 | } 39 | fps operator%(const fps& r) const { return *this - *this / r * r; } 40 | fps operator<<(int s) const { 41 | vm res(size() + s); 42 | rep(i, size()) res[i + s] = v[i]; 43 | return res; 44 | } 45 | fps operator>>(int s) const { 46 | if(size() <= s) return fps(); 47 | vm res(size() - s); 48 | rep(i, size() - s) res[i] = v[i + s]; 49 | return res; 50 | } 51 | fps& operator+=(const fps& r) { return *this = *this + r; } 52 | fps& operator-=(const fps& r) { return *this = *this - r; } 53 | fps& operator*=(const fps& r) { return *this = *this * r; } 54 | fps& operator*=(const mint& r) { return *this = *this * r; } 55 | fps& operator/=(const fps& r) { return *this = *this / r; } 56 | fps& operator/=(const mint& r) { return *this = *this / r; } 57 | fps& operator%=(const fps& r) { return *this = *this % r; } 58 | fps& operator<<=(int n) { return *this = *this << n; } 59 | fps& operator>>=(int n) { return *this = *this >> n; } 60 | fps rev(int n = -1) const { 61 | vm res = v; 62 | if(n != -1) res.resize(n); 63 | reverse(res.begin(), res.end()); 64 | return res; 65 | } 66 | fps diff() const { 67 | vm res(max(0, size() - 1)); 68 | rep(i, 1, size()) res[i - 1] = freq(i) * i; 69 | return res; 70 | } 71 | fps integ() const { 72 | vm res(size() + 1); 73 | rep(i, size()) res[i + 1] = freq(i) / (i + 1); 74 | return res; 75 | } 76 | // f * f.inv() = 1 + g(x)x^m 77 | fps inv(int m) const { 78 | fps res = fps(vm{mint(1) / freq(0)}); 79 | for(int i = 1; i < m; i *= 2) { res = (res * mint(2) - res * res * pre(2 * i)).pre(2 * i); } 80 | return res.pre(m); 81 | } 82 | fps exp(int n) const { 83 | assert(freq(0).x == 0); 84 | fps g = fps(vm{1}); 85 | for(int i = 1; i < n; i *= 2) { g = (g * (pre(i * 2) + fps(vm{1}) - g.log(i * 2))).pre(i * 2); } 86 | return g.pre(n); 87 | } 88 | fps log(int n) const { 89 | assert(freq(0).x == 1); 90 | auto f = pre(n); 91 | return (f.diff() * f.inv(n - 1)).pre(n - 1).integ(); 92 | } 93 | fps sqrt(int n) const { 94 | assert(freq(0).x == 1); 95 | fps f = pre(n + 1); 96 | fps g({1}); 97 | for(int i = 1; i < n; i *= 2) { g = (g + f.pre(2 * i) * g.inv(2 * i)) * mint((mod + 1) / 2); } 98 | return g.pre(n + 1); 99 | } 100 | fps pow(ll k, ll n) { 101 | if(k == 0) { 102 | fps res(n); 103 | res[0] = 1; 104 | return res; 105 | } 106 | rep(i, size()) { 107 | if((*this)[i].x) { 108 | mint rev = mint(1) / (*this)[i]; 109 | fps ret = (((*this * rev) >> i).log(n) * mint(k)).exp(n); 110 | ret *= (*this)[i].pow(k); 111 | ret = (ret << (i * k)).pre(n); 112 | if(ret.size() < n) ret.resize(n); 113 | return ret; 114 | } 115 | if(i128(i + 1) * k >= n) return fps(n); 116 | } 117 | return fps(n); 118 | } 119 | fps pow_mod(ll n, const fps& mod) { 120 | fps x = *this, r = {{1}}; 121 | while(n) { 122 | if(n & 1) r = r * x % mod; 123 | x = x * x % mod; 124 | n >>= 1; 125 | } 126 | return r; 127 | } 128 | }; 129 | -------------------------------------------------------------------------------- /src/FPS/relaxed-convolution.hpp: -------------------------------------------------------------------------------- 1 | struct relaxed_multiplication { 2 | vector f, g, h; 3 | 4 | // fg_prefix_ntts[d] = (NTTs of first 2^d terms of f and g) 5 | vector, vector>> fg_prefix_ntts; 6 | 7 | const auto& get_fg_prefix_ntt(int d) { 8 | while(int(fg_prefix_ntts.size()) <= d) { 9 | int fftlen = 1 << fg_prefix_ntts.size(); 10 | vector vf(f.begin(), f.begin() + fftlen); 11 | vector vg(g.begin(), g.begin() + fftlen); 12 | ntt(vf, false), ntt(vg, false); 13 | fg_prefix_ntts.emplace_back(vf, vg); 14 | } 15 | return fg_prefix_ntts[d]; 16 | } 17 | 18 | relaxed_multiplication() {} 19 | 20 | mint add(const mint& f_i, const mint& g_i) { 21 | f.push_back(f_i), g.push_back(g_i); 22 | const int n = f.size(), d = __builtin_ctz(n), D = 1 << d; 23 | 24 | if(int gsz = n - 1 + D; h.size() < gsz) h.resize(gsz); 25 | 26 | if(n == D) { 27 | // Convolve f[0, D) * g[0, D) -> h[D - 1, D * 2 - 1) 28 | 29 | const auto& [nttf, nttg] = get_fg_prefix_ntt(d); 30 | vector tmp(nttf.size()); 31 | for(int i = 0; i < nttf.size(); ++i) tmp[i] = nttf[i] * nttg[i]; 32 | ntt(tmp, true); 33 | 34 | for(int i = 0; i < n - 1; ++i) h[n + i] += tmp[i] - h[i]; // 回り込みを削除 35 | h[n - 1] += tmp[n - 1]; 36 | } else { 37 | // Convolve f[0, 2 * D) * g[n - D, n) -> h[n - 1, n - 1 + D) 38 | 39 | if(d <= 4) { // Bruteforce threshold 40 | for(int i = n - D; i < n; ++i) { 41 | for(int k = n - 1; k < n - 1 + D; ++k) { h[k] += f[i] * g[k - i] + f[k - i] * g[i]; } 42 | } 43 | } else { 44 | vector tmpf{f.end() - D, f.end()}, tmpg{g.end() - D, g.end()}; 45 | tmpf.resize(D * 2), tmpg.resize(D * 2); 46 | ntt(tmpf, false), ntt(tmpg, false); 47 | 48 | const auto& [nttf, nttg] = get_fg_prefix_ntt(d + 1); 49 | for(int i = 0; i < tmpf.size(); ++i) { tmpf[i] = tmpf[i] * nttg[i] + tmpg[i] * nttf[i]; } 50 | ntt(tmpf, true); 51 | for(int i = 0; i < D; ++i) h[n - 1 + i] += tmpf[D - 1 + i]; 52 | } 53 | } 54 | 55 | return h[n - 1]; 56 | } 57 | }; -------------------------------------------------------------------------------- /src/data-structure/BIT.hpp: -------------------------------------------------------------------------------- 1 | struct BIT { 2 | vl a; 3 | BIT(ll n) : a(n + 1) {} 4 | void add(ll i, ll x) { 5 | i++; 6 | while(i < si(a)) a[i] += x, i += i & -i; 7 | } 8 | ll sum(ll r) { 9 | ll s = 0; 10 | while(r) s += a[r], r -= r & -r; 11 | return s; 12 | } 13 | ll sum(ll l, ll r) { return sum(r) - sum(l); } 14 | // minimize i s.t. sum(i) >= w 15 | int lower_bound(ll w) { 16 | if(w <= 0) return 0; 17 | int x = 0, N = si(a) + 1; 18 | for(int k = 1 << __lg(N); k; k >>= 1) { 19 | if(x + k <= N - 1 && a[x + k] < w) { 20 | w -= a[x + k]; 21 | x += k; 22 | } 23 | } 24 | return x; 25 | } 26 | }; -------------------------------------------------------------------------------- /src/data-structure/FastSet.hpp: -------------------------------------------------------------------------------- 1 | 2 | using U = uint64_t; 3 | const U B = 64; 4 | struct FS { 5 | U n; 6 | vector> a; 7 | FS(U n) : n(n) { 8 | do a.eb(n = (n + B - 1) / B); 9 | while(n > 1); 10 | } 11 | bool operator[](ll i) const { return a[0][i / B] >> (i % B) & 1; } 12 | void set(ll i) { 13 | for(auto& v : a) { 14 | v[i / B] |= 1ULL << (i % B); 15 | i /= B; 16 | } 17 | } 18 | void erase(ll i) { 19 | for(auto& v : a) { 20 | v[i / B] &= ~(1ULL << (i % B)); 21 | if(v[i / B]) break; 22 | i /= B; 23 | } 24 | } 25 | ll next(ll i) { 26 | rep(h, si(a)) { 27 | i++; 28 | if(i / B >= si(a[h])) break; 29 | U d = a[h][i / B] >> (i % B); 30 | if(d) { 31 | i += countr_zero(d); 32 | while(h--) i = i * B + countr_zero(a[h][i]); 33 | return i; 34 | } 35 | i /= B; 36 | } 37 | return n; 38 | } 39 | ll prev(ll i) { 40 | rep(h, si(a)) { 41 | i--; 42 | if(i < 0) break; 43 | U d = a[h][i / B] << (~i % B); 44 | if(d) { 45 | i -= countl_zero(d); 46 | while(h--) i = i * B + __lg(a[h][i]); 47 | return i; 48 | } 49 | i /= B; 50 | } 51 | return -1; 52 | } 53 | }; -------------------------------------------------------------------------------- /src/data-structure/Skew-Heap.hpp: -------------------------------------------------------------------------------- 1 | template struct SkewHeap { 2 | struct Node { 3 | T key, laz; 4 | Node *l, *r; 5 | int idx; 6 | Node() = default; 7 | Node(const T& k, int i = -1) : key(k), laz(0), l(nullptr), r(nullptr), idx(i) {} 8 | }; 9 | using P = Node*; 10 | static void propagate(P x) { 11 | if(x->laz == 0) return; 12 | if(x->l) x->l->laz += x->laz; 13 | if(x->r) x->r->laz += x->laz; 14 | x->key += x->laz; 15 | x->laz = 0; 16 | } 17 | static P meld(P x, P y) { 18 | if(!x || !y) return x ? x : y; 19 | if(!comp(x, y)) swap(x, y); 20 | propagate(x); 21 | x->r = meld(x->r, y); 22 | swap(x->l, x->r); 23 | return x; 24 | } 25 | static P alloc(const T& key, int idx = -1) { return new Node(key, idx); } 26 | static P pop(P x) { 27 | propagate(x); 28 | return meld(x->l, x->r); 29 | } 30 | static P push(P x, const T& key, int idx = -1) { return meld(x, alloc(key, idx)); } 31 | static void apply(P x, const T& laz) { 32 | x->laz += laz; 33 | propagate(x); 34 | } 35 | 36 | private: 37 | static inline bool comp(P x, P y) { 38 | if constexpr(isMin) { 39 | return x->key + x->laz < y->key + y->laz; 40 | } else { 41 | return x->key + x->laz > y->key + y->laz; 42 | } 43 | } 44 | }; -------------------------------------------------------------------------------- /src/data-structure/cht.hpp: -------------------------------------------------------------------------------- 1 | template struct CHT { 2 | #define x first 3 | #define y second 4 | CHT() = default; 5 | deque v; 6 | bool empty() { return v.empty(); } 7 | void clear() { return v.clear(); } 8 | inline int sgn(ll x) { return !x ? 0 : (x < 0 ? -1 : 1); } 9 | using D = long double; 10 | inline bool check(const pll& a, const pll& b, const pll& c) { 11 | if(b.y == a.y or c.y == b.y) return sgn(b.x - a.x) * sgn(c.y - b.y) >= sgn(c.x - b.x) * sgn(b.y - a.y); 12 | return D(b.x - a.x) * sgn(c.y - b.y) / D(abs(b.y - a.y)) >= D(c.x - b.x) * sgn(b.y - a.y) / D(abs(c.y - b.y)); 13 | } 14 | void add(ll a, ll b) { 15 | if(!isMin) a *= -1, b *= -1; 16 | pll line(a, b); 17 | if(empty()) v.emplace_front(line); 18 | else { 19 | if(ll c = v[0].x; c <= a) { 20 | if(c == a) { 21 | if(v[0].y <= b) return; 22 | v.pop_front(); 23 | } 24 | while(si(v) >= 2 and check(line, v[0], v[1])) v.pop_front(); 25 | v.emplace_front(line); 26 | } else { 27 | assert(a <= v.back().x); 28 | if(v.back().x == a) { 29 | if(v.back().y <= b) return; 30 | v.pop_back(); 31 | } 32 | while(si(v) >= 2 and check(v[si(v) - 2], v.back(), line)) v.pop_back(); 33 | v.emplace_back(line); 34 | } 35 | } 36 | } 37 | ll get_y(const pll& a, const ll& x) { return a.x * x + a.y; } 38 | ll query(ll x) { 39 | assert(!empty()); 40 | int l = -1, r = si(v) - 1; 41 | while(l + 1 < r) { 42 | int m = (l + r) >> 1; 43 | if(get_y(v[m], x) >= get_y(v[m + 1], x)) l = m; 44 | else r = m; 45 | } 46 | return get_y(v[r], x) * (isMin ? 1 : -1); 47 | } 48 | ll query_monotone_inc(ll x) { 49 | assert(!empty()); 50 | while(si(v) >= 2 and get_y(v[0], x) >= get_y(v[1], x)) v.pop_front(); 51 | return get_y(v[0], x) * (isMin ? 1 : -1); 52 | } 53 | ll query_monotone_dec(ll x) { 54 | assert(!empty()); 55 | while(si(v) >= 2 and get_y(v.back(), x) >= get_y(v.end()[-2], x)) v.pop_back(); 56 | return get_y(v.back(), x) * (isMin ? 1 : -1); 57 | } 58 | #undef x 59 | #undef y 60 | }; -------------------------------------------------------------------------------- /src/data-structure/hash_map.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | struct chash { 3 | const uint64_t C = (ll)(4e18 * acos(0)) | 71; 4 | ll operator()(ll x) const { return __builtin_bswap64(x * C); } 5 | }; 6 | using namespace __gnu_pbds; 7 | template using hash_map = gp_hash_table; -------------------------------------------------------------------------------- /src/data-structure/lazy-segtree.hpp: -------------------------------------------------------------------------------- 1 | using U = uint64_t; 2 | template struct lazy_segtree { 3 | lazy_segtree() : lazy_segtree(0) {} 4 | explicit lazy_segtree(int n) : lazy_segtree(vector(n, e())) {} 5 | explicit lazy_segtree(const vector& v) : n(si(v)) { 6 | s = bit_ceil(U(n)); 7 | log = countr_zero(U(s)); 8 | d = vector(2 * s, e()); 9 | lz = vector(s, id()); 10 | rep(i, n) d[s + i] = v[i]; 11 | per(i, s, 1) update(i); 12 | } 13 | void set(int p, S x) { 14 | p += s; 15 | PUSH(p); 16 | d[p] = x; 17 | rep(i, 1, log + 1) update(p >> i); 18 | } 19 | S get(int p) { 20 | p += s; 21 | PUSH(p); 22 | return d[p]; 23 | } 24 | S prod(int l, int r) { 25 | if(l == r) return e(); 26 | l += s, r += s; 27 | per(i, log + 1, 1) { 28 | if(((l >> i) << i) != l) push(l >> i); 29 | if(((r >> i) << i) != r) push((r - 1) >> i); 30 | } 31 | S sml = e(), smr = e(); 32 | while(l < r) { 33 | if(l & 1) sml = op(sml, d[l++]); 34 | if(r & 1) smr = op(d[--r], smr); 35 | l >>= 1, r >>= 1; 36 | } 37 | return op(sml, smr); 38 | } 39 | S all_prod() { return d[1]; } 40 | void apply(int p, F f) { 41 | // assert(0 <= p && p < n); 42 | p += s; 43 | PUSH(p); 44 | d[p] = mpp(f, d[p]); 45 | rep(i, 1, log + 1) update(p >> i); 46 | } 47 | void apply(int l, int r, F f) { 48 | // assert(0 <= l && l <= r && r <= _n); 49 | if(l == r) return; 50 | l += s, r += s; 51 | 52 | per(i, log + 1, 1) { 53 | if(((l >> i) << i) != l) push(l >> i); 54 | if(((r >> i) << i) != r) push((r - 1) >> i); 55 | } 56 | int ml = l, mr = r; 57 | while(l < r) { 58 | if(l & 1) all_apply(l++, f); 59 | if(r & 1) all_apply(--r, f); 60 | l >>= 1, r >>= 1; 61 | } 62 | l = ml, r = mr; 63 | rep(i, 1, log + 1) { 64 | if(((l >> i) << i) != l) update(l >> i); 65 | if(((r >> i) << i) != r) update((r - 1) >> i); 66 | } 67 | } 68 | template int max_right(int l, G g) { 69 | assert(g(e())); 70 | if(l == n) return n; 71 | l += s; 72 | PUSH(l); 73 | S sm = e(); 74 | do { 75 | while(~l & 1) l >>= 1; 76 | if(!g(op(sm, d[l]))) { 77 | while(l < s) { 78 | push(l); 79 | l <<= 1; 80 | if(g(op(sm, d[l]))) { 81 | sm = op(sm, d[l]); 82 | l++; 83 | } 84 | } 85 | return l - s; 86 | } 87 | sm = op(sm, d[l]); 88 | l++; 89 | } while((l & -l) != l); 90 | return n; 91 | } 92 | template int min_left(int r, G g) { 93 | assert(g(e())); 94 | if(r == 0) return 0; 95 | r += s; 96 | PUSH(r - 1); 97 | S sm = e(); 98 | do { 99 | r--; 100 | while(r > 1 && r & 1) r >>= 1; 101 | if(!g(op(d[r], sm))) { 102 | while(r < s) { 103 | push(r); 104 | r = (2 * r + 1); 105 | if(g(op(d[r], sm))) { 106 | sm = op(d[r], sm); 107 | r--; 108 | } 109 | } 110 | return r + 1 - s; 111 | } 112 | sm = op(d[r], sm); 113 | } while((r & -r) != r); 114 | return 0; 115 | } 116 | S operator[](int k) { return get(k); } 117 | int len() { return n; } 118 | 119 | private: 120 | int n, s, log; 121 | vector d; 122 | vector lz; 123 | void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); } 124 | void all_apply(int k, F f) { 125 | d[k] = mpp(f, d[k]); 126 | if(k < s) lz[k] = cmpo(f, lz[k]); 127 | } 128 | void push(int k) { 129 | all_apply(2 * k, lz[k]); 130 | all_apply(2 * k + 1, lz[k]); 131 | lz[k] = id(); 132 | } 133 | void PUSH(int k) { per(i, log + 1, 1) push(k >> i); } 134 | }; -------------------------------------------------------------------------------- /src/data-structure/li-chao.hpp: -------------------------------------------------------------------------------- 1 | 2 | struct lctree { 3 | struct line { 4 | ll a, b; 5 | line() : a(0), b(INFL) {} 6 | line(ll a, ll b) : a(a), b(b) {} 7 | ll get(ll x) { return a * x + b; } 8 | inline bool over(line r, ll x) { return get(x) < r.get(x); } 9 | }; 10 | int n; 11 | 12 | vector x; 13 | vector seg; 14 | lctree() {} 15 | lctree(const vector& _x) : x(_x) { 16 | sort(all(x)); 17 | int n2 = si(x); 18 | n = 1; 19 | while(n < n2) n <<= 1; 20 | x.resize(n); 21 | rep(i, n2, n) x[i] = x[n2 - 1]; 22 | seg = vector(n * 2); 23 | } 24 | void upd(line L, int i, int l, int r) { 25 | while(true) { 26 | int mid = l + r >> 1; 27 | bool lov = L.over(seg[i], x[l]); 28 | bool rov = L.over(seg[i], x[r - 1]); 29 | if(lov == rov) { 30 | if(lov) swap(seg[i], L); 31 | return; 32 | } 33 | bool mov = L.over(seg[i], x[mid]); 34 | if(mov) swap(seg[i], L); 35 | if(lov != mov) { 36 | i = (i << 1), r = mid; 37 | } else { 38 | i = (i << 1) + 1, l = mid; 39 | } 40 | } 41 | } 42 | void upd(line L, unsigned i) { 43 | int ub = bit_width(i) - 1; 44 | int l = (n >> ub) * (i - (1 << ub)); 45 | int r = l + (n >> ub); 46 | upd(L, i, l, r); 47 | } 48 | void update(ll a, ll b) { upd(line(a, b), 1, 0, n); } 49 | void update_segment(ll l, ll r, ll a, ll b) { 50 | l = lb(x, l) + n, r = lb(x, r) + n; 51 | line L(a, b); 52 | for(; l < r; l >>= 1, r >>= 1) { 53 | if(l & 1) upd(L, l++); 54 | if(r & 1) upd(L, --r); 55 | } 56 | } 57 | ll query(ll t) { 58 | ll k = lb(x, t); 59 | k += n; 60 | ll res = seg[k].get(t); 61 | while(k > 1) { 62 | k >>= 1; 63 | chmin(res, seg[k].get(t)); 64 | } 65 | return res; 66 | } 67 | }; -------------------------------------------------------------------------------- /src/data-structure/line_container.hpp: -------------------------------------------------------------------------------- 1 | struct Line { 2 | mutable ll k, m, p; 3 | bool operator<(const Line& o) const { return k < o.k; } 4 | bool operator<(ll x) const { return p < x; } 5 | }; 6 | 7 | template struct LineContainer : multiset> { 8 | // (for doubles, use inf = 1/.0, div(a,b) = a/b) 9 | const ll inf = LLONG_MAX / 2; 10 | ll div(ll a, ll b) { // floored division 11 | return a / b - ((a ^ b) < 0 && a % b); 12 | } 13 | bool isect(iterator x, iterator y) { 14 | if(y == end()) { 15 | x->p = inf; 16 | return false; 17 | } 18 | if(x->k == y->k) x->p = x->m > y->m ? inf : -inf; 19 | else x->p = div(y->m - x->m, x->k - y->k); 20 | return x->p >= y->p; 21 | } 22 | void add(ll k, ll m) { 23 | if(ismin) k = -k, m = -m; 24 | auto z = insert({k, m, 0}), y = z++, x = y; 25 | while(isect(y, z)) z = erase(z); 26 | if(x != begin() && isect(--x, y)) isect(x, y = erase(y)); 27 | while((y = x) != begin() && (--x)->p >= y->p) isect(x, erase(y)); 28 | } 29 | ll query(ll x) { 30 | auto l = *lower_bound(x); 31 | ll s = 1; 32 | if(ismin) s = -1; 33 | return s * (l.k * x + l.m); 34 | } 35 | }; -------------------------------------------------------------------------------- /src/data-structure/link-cut.hpp: -------------------------------------------------------------------------------- 1 | struct Node { 2 | typedef Node* NP; 3 | NP l, r, p; 4 | bool rev; 5 | int v, mx, lz; 6 | Node() : l(NULL), r(NULL), p(NULL), rev(false), v(-inf), mx(-inf), lz(-inf) {} 7 | void Propagate() { 8 | if(rev) { 9 | swap(l, r); 10 | if(l) l->rev ^= true; 11 | if(r) r->rev ^= true; 12 | rev = false; 13 | } 14 | if(l) chmax(l->lz, lz); 15 | if(r) chmax(r->lz, lz); 16 | chmax(v, lz); 17 | chmax(mx, lz); 18 | lz = -inf; 19 | } 20 | int GetMax() { return max(mx, lz); } 21 | int GetVert() { return max(v, lz); } 22 | void Update() { 23 | assert(lz == -inf); 24 | mx = v; 25 | if(l) { chmax(mx, l->GetMax()); } 26 | if(r) { chmax(mx, r->GetMax()); } 27 | } 28 | int Pos() { 29 | if(p && p->l == this) return -1; 30 | if(p && p->r == this) return 1; 31 | return 0; 32 | } 33 | void Prepare() { 34 | if(Pos()) p->Prepare(); 35 | Propagate(); 36 | } 37 | void Rotate() { 38 | NP q = p, c; 39 | if(Pos() == 1) { 40 | c = l; 41 | l = p; 42 | p->r = c; 43 | } else { 44 | c = r; 45 | r = p; 46 | p->l = c; 47 | } 48 | if(c) c->p = p; 49 | p = p->p; 50 | q->p = this; 51 | if(p && p->l == q) p->l = this; 52 | if(p && p->r == q) p->r = this; 53 | q->Update(); 54 | } 55 | void Splay() { 56 | Prepare(); 57 | while(Pos()) { 58 | int a = Pos(), b = p->Pos(); 59 | if(b && a == b) p->Rotate(); 60 | if(b && a != b) Rotate(); 61 | Rotate(); 62 | } 63 | Update(); 64 | } 65 | void Expose() { 66 | for(NP x = this; x; x = x->p) x->Splay(); 67 | for(NP x = this; x->p; x = x->p) { 68 | x->p->r = x; 69 | x->p->Update(); 70 | } 71 | Splay(); 72 | } 73 | void Evert() { 74 | Expose(); 75 | if(l) { 76 | l->rev ^= true; 77 | l = NULL; 78 | Update(); 79 | } 80 | } 81 | void Link(NP x) { 82 | Evert(); 83 | p = x; 84 | } 85 | void Set(int q) { 86 | Expose(); 87 | r = NULL; 88 | chmax(lz, q); 89 | } 90 | void Cut() { 91 | Expose(); 92 | assert(l); 93 | l->p = NULL; 94 | l = NULL; 95 | Update(); 96 | } 97 | int Get() { 98 | Expose(); 99 | r = NULL; 100 | Update(); 101 | return GetMax(); 102 | } 103 | }; 104 | Node* LCA(Node* a, Node* b) { 105 | a->Expose(); 106 | b->Expose(); 107 | if(!a->p) { return NULL; } 108 | Node* d = a; 109 | while(a->p != b) { 110 | if(a->Pos() == 0) { d = a->p; } 111 | a = a->p; 112 | } 113 | if(a == b->l) { 114 | return d; 115 | } else { 116 | return b; 117 | } 118 | } -------------------------------------------------------------------------------- /src/data-structure/pbds.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace __gnu_pbds; 6 | // using namespace __gnu_pbds; 7 | template using PQ = __gnu_pbds::priority_queue, __gnu_pbds::rc_binomial_heap_tag>; 8 | using Trie = __gnu_pbds::trie, 11 | __gnu_pbds::pat_trie_tag, 12 | __gnu_pbds::trie_prefix_search_node_update>; 13 | // not a multiset 14 | // find_by_order(k) -> itr of k-th(0-based) element 15 | // order_of_key(k) -> index of lower_bound(k) 16 | using ordered_set = tree, rb_tree_tag, tree_order_statistics_node_update>; 17 | 18 | #include 19 | using namespace __gnu_cxx; -------------------------------------------------------------------------------- /src/data-structure/rbst.hpp: -------------------------------------------------------------------------------- 1 | 2 | template struct RBST { 3 | inline int rnd() { 4 | static int x = 123456789; 5 | static int y = 362436069; 6 | static int z = 521288629; 7 | static int w = 88675123; 8 | int t; 9 | 10 | t = x ^ (x << 11); 11 | x = y; 12 | y = z; 13 | z = w; 14 | return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); 15 | } 16 | struct node { 17 | node *l, *r; 18 | int cnt; 19 | T x, sum; 20 | node() = default; 21 | node(T x) : x(x), sum(x), l(0), r(0) { cnt = 1; } 22 | }; 23 | RBST(int n) : pool(n) {} 24 | int cnt(const node* t) { return t ? t->cnt : 0; } 25 | T sum(const node* t) { return t ? t->sum : e(); } 26 | node* update(node* t) { 27 | t->cnt = cnt(t->l) + cnt(t->r) + 1; 28 | t->sum = f(f(sum(t->l), t->x), sum(t->r)); 29 | return t; 30 | } 31 | vector pool; 32 | int ptr = 0; 33 | inline node* alloc(const T& v) { 34 | if(si(pool) == ptr) pool.resize(si(pool) * 2); 35 | return &(pool[ptr++] = node(v)); 36 | } 37 | node* merge(node* l, node* r) { 38 | if(!l or !r) return l ? l : r; 39 | if(rnd() % (cnt(l) + cnt(r)) < cnt(l)) { 40 | l->r = merge(l->r, r); 41 | return update(l); 42 | } 43 | r->l = merge(l, r->l); 44 | return update(r); 45 | } 46 | 47 | pair split(node* t, int k) { 48 | if(!t) return {t, t}; 49 | if(k <= cnt(t->l)) { 50 | auto [l, r] = split(t->l, k); 51 | t->l = r; 52 | return {l, update(t)}; 53 | } 54 | auto [l, r] = split(t->r, k - cnt(t->l) - 1); 55 | t->r = l; 56 | return {update(t), r}; 57 | } 58 | 59 | void insert(node*& t, int k, const T& v) { 60 | auto [l, r] = split(t, k); 61 | t = merge(merge(l, alloc(v)), r); 62 | } 63 | }; -------------------------------------------------------------------------------- /src/data-structure/segbeats.hpp: -------------------------------------------------------------------------------- 1 | 2 | struct Segtree_beats { 3 | ll op(int type, ll x, ll y) { return type ? min(x, y) : max(x, y); } 4 | bool cmp(int type, ll x, ll y) { return type ? x < y : x > y; } 5 | struct alignas(32) Node { 6 | ll sum = 0; 7 | ll a1[2] = {}, a2[2] = {-INFL, INFL}, ac[2] = {1, 1}, add = 0; 8 | }; 9 | 10 | vector v; 11 | ll n, log, e[3] = {-INFL, INFL, 0}; 12 | 13 | Segtree_beats() {} 14 | Segtree_beats(int n) : Segtree_beats(vl(n)) {} 15 | Segtree_beats(const vl& a) { 16 | n = 1, log = 0; 17 | while(n < si(a)) n <<= 1, log++; 18 | v.resize(2 * n); 19 | rep(i, si(a)) { v[i + n].sum = v[i + n].a1[0] = v[i + n].a1[1] = a[i]; } 20 | per(i, n, 1) update(i); 21 | } 22 | 23 | // 0 : add, 1 : chmin, 2 : chmax, 3 : update 24 | template void apply(int l, int r, ll x) { 25 | if(l == r) return; 26 | l += n, r += n; 27 | per(i, log + 1, 1) { 28 | if(((l >> i) << i) != l) push(l >> i); 29 | if(((r >> i) << i) != r) push((r - 1) >> i); 30 | } 31 | { 32 | int l2 = l, r2 = r; 33 | while(l < r) { 34 | if(l & 1) _apply(l++, x); 35 | if(r & 1) _apply(--r, x); 36 | l >>= 1; 37 | r >>= 1; 38 | } 39 | l = l2; 40 | r = r2; 41 | } 42 | rep(i, 1, log + 1) { 43 | if(((l >> i) << i) != l) update(l >> i); 44 | if(((r >> i) << i) != r) update((r - 1) >> i); 45 | } 46 | } 47 | // 0 : max, 1 : min, 2 : sum 48 | template ll fold(int l, int r) { 49 | if(l == r) return e[cmd]; 50 | l += n, r += n; 51 | per(i, log + 1, 1) { 52 | if(((l >> i) << i) != l) push(l >> i); 53 | if(((r >> i) << i) != r) push((r - 1) >> i); 54 | } 55 | ll lx = e[cmd], rx = e[cmd]; 56 | while(l < r) { 57 | if(l & 1) op(lx, v[l++]); 58 | if(r & 1) op(rx, v[--r]); 59 | l >>= 1; 60 | r >>= 1; 61 | } 62 | if constexpr(cmd <= 1) lx = op(cmd, lx, rx); 63 | if constexpr(cmd == 2) lx += rx; 64 | return lx; 65 | } 66 | 67 | private: 68 | void update(int k) { 69 | Node& p = v[k]; 70 | Node& l = v[k * 2 + 0]; 71 | Node& r = v[k * 2 + 1]; 72 | p.sum = l.sum + r.sum; 73 | rep(t, 2) { 74 | if(l.a1[t] == r.a1[t]) { 75 | p.a1[t] = l.a1[t]; 76 | p.a2[t] = op(t, l.a2[t], r.a2[t]); 77 | p.ac[t] = l.ac[t] + r.ac[t]; 78 | } else { 79 | bool f = cmp(t, l.a1[t], r.a1[t]); 80 | p.a1[t] = f ? l.a1[t] : r.a1[t]; 81 | p.ac[t] = f ? l.ac[t] : r.ac[t]; 82 | p.a2[t] = op(t, f ? r.a1[t] : l.a1[t], f ? l.a2[t] : r.a2[t]); 83 | } 84 | } 85 | } 86 | 87 | void push_add(int k, ll x) { 88 | Node& p = v[k]; 89 | p.sum += x << (log + __builtin_clz(k) - 31); 90 | rep(t, 2) { 91 | p.a1[t] += x; 92 | if(p.a2[t] != e[t]) p.a2[t] += x; 93 | } 94 | p.add += x; 95 | } 96 | 97 | void push(int cmd, int k, ll x) { 98 | Node& p = v[k]; 99 | p.sum += (x - p.a1[cmd]) * p.ac[cmd]; 100 | if(p.a1[cmd ^ 1] == p.a1[cmd]) p.a1[cmd ^ 1] = x; 101 | if(p.a2[cmd ^ 1] == p.a1[cmd]) p.a2[cmd ^ 1] = x; 102 | p.a1[cmd] = x; 103 | } 104 | void push(int k) { 105 | Node& p = v[k]; 106 | if(p.add) { 107 | rep(t, 2) push_add(k * 2 + t, p.add); 108 | p.add = 0; 109 | } 110 | rep(t, 2) rep(s, 2) if(cmp(t, v[k * 2 + s].a1[t], p.a1[t])) push(t, k * 2 + s, p.a1[t]); 111 | } 112 | 113 | void subtree_ch(int cmd, int k, ll x) { 114 | if(!cmp(cmd, v[k].a1[cmd], x)) return; 115 | if(cmp(cmd, x, v[k].a2[cmd])) { return push(cmd, k, x); } 116 | push(k); 117 | rep(t, 2) subtree_ch(cmd, k * 2 + t, x); 118 | update(k); 119 | } 120 | 121 | template inline void _apply(int k, ll x) { 122 | rep(i, 2) if(cmd >> i & 1) subtree_ch(i, k, x); 123 | if constexpr(cmd == 0) push_add(k, x); 124 | } 125 | 126 | template inline void op(ll& a, const Node& b) { 127 | if constexpr(cmd <= 1) a = op(cmd, a, b.a1[cmd]); 128 | if constexpr(cmd == 2) a += b.sum; 129 | } 130 | }; -------------------------------------------------------------------------------- /src/data-structure/segtree-2d.hpp: -------------------------------------------------------------------------------- 1 | 2 | template class RangeTree { 3 | private: 4 | int n, sz; 5 | vector> seg; 6 | vector> yx; 7 | vector sorted; 8 | 9 | void update_(int id, ll x, ll y, T val) { 10 | id += n - 1; 11 | int yid = lb(yx[id], pll(y, x)); 12 | seg[id].set(yid, val); 13 | while(id > 0) { 14 | id = (id - 1) / 2; 15 | int yid = lb(yx[id], pll(y, x)); 16 | seg[id].set(yid, val); 17 | } 18 | } 19 | T query(int lxid, int rxid, ll ly, ll ry, int k, int l, int r) { 20 | if(r <= lxid || rxid <= l) return e(); 21 | if(lxid <= l && r <= rxid) { 22 | int lyid = lb(yx[k], pll(ly, -INFL)); 23 | int ryid = lb(yx[k], pll(ry, -INFL)); 24 | return (lyid >= ryid) ? e() : seg[k].prod(lyid, ryid); 25 | } else { 26 | return op(query(lxid, rxid, ly, ry, 2 * k + 1, l, (l + r) / 2), 27 | query(lxid, rxid, ly, ry, 2 * k + 2, (l + r) / 2, r)); 28 | } 29 | } 30 | 31 | public: 32 | // 座標, 点の値 33 | RangeTree(vector& cand, vector& val) : n(1), sz(si(cand)), sorted(sz) { 34 | while(n < sz) n *= 2; 35 | rep(i, sz) sorted[i] = {cand[i].first, i}; 36 | sort(all(sorted), [&](pll& a, pll& b) { 37 | return (a.first == b.first) ? (cand[a.second].second < cand[b.second].second) : (a.first < b.first); 38 | }); 39 | yx.resize(2 * n - 1), seg.resize(2 * n - 1); 40 | rep(i, sz) { 41 | yx[i + n - 1] = {{sorted[i].second, sorted[i].first}}; 42 | vector arg = {val[sorted[i].second]}; 43 | seg[i + n - 1] = segtree(arg); 44 | sorted[i].second = cand[sorted[i].second].second; 45 | } 46 | per(i, n - 1, 0) { 47 | yx[i].resize(si(yx[2 * i + 1]) + si(yx[2 * i + 2])); 48 | if(yx[i].empty()) continue; 49 | merge(all(yx[2 * i + 1]), all(yx[2 * i + 2]), yx[i].begin(), [&](pll& a, pll& b) { 50 | return (cand[a.first].second == cand[b.first].second) ? (a.second < b.second) 51 | : (cand[a.first].second < cand[b.first].second); 52 | }); 53 | vector arg((int)yx[i].size()); 54 | rep(j, si(yx[i])) arg[j] = val[yx[i][j].first]; 55 | seg[i] = segtree(arg); 56 | } 57 | rep(i, 2 * n - 1) { 58 | for(auto& [a, b] : yx[i]) a = cand[a].second; 59 | } 60 | } 61 | void update(ll x, ll y, T val) { 62 | int id = lb(sorted, pll(x, y)); 63 | return update_(id, x, y, val); 64 | } 65 | T query(ll lx, ll ly, ll rx, ll ry) { 66 | int lxid = lb(sorted, pll(lx, -INFL)); 67 | int rxid = lb(sorted, pll(rx, -INFL)); 68 | return (lxid >= rxid) ? e() : query(lxid, rxid, ly, ry, 0, 0, n); 69 | } 70 | }; -------------------------------------------------------------------------------- /src/data-structure/segtree.hpp: -------------------------------------------------------------------------------- 1 | template struct segtree { 2 | segtree(int n) : segtree(vector(n, e())) {} 3 | segtree(const vector& v) : n(si(v)) { 4 | s = bit_ceil(unsigned(n)); 5 | log = countr_zero(unsigned(s)); 6 | d = vector(2 * s, e()); 7 | rep(i, n) d[s + i] = v[i]; 8 | per(i, s, 1) update(i); 9 | } 10 | void set(int p, S x) { 11 | d[p += s] = x; 12 | rep(i, 1, log + 1) update(p >> i); 13 | } 14 | S prod(int l, int r) const { 15 | S sml = e(), smr = e(); 16 | l += s, r += s; 17 | while(l < r) { 18 | if(l & 1) sml = op(sml, d[l++]); 19 | if(r & 1) smr = op(d[--r], smr); 20 | l >>= 1, r >>= 1; 21 | } 22 | return op(sml, smr); 23 | } 24 | S all_prod() const { return d[1]; } 25 | template int max_right(int l, F f) const { 26 | if(l == n) return n; 27 | l += s; 28 | S sm = e(); 29 | do { 30 | while(~l & 1) l >>= 1; 31 | if(!f(op(sm, d[l]))) { 32 | while(l < s) { 33 | l <<= 1; 34 | if(f(op(sm, d[l]))) sm = op(sm, d[l++]); 35 | } 36 | return l - s; 37 | } 38 | sm = op(sm, d[l++]); 39 | } while((l & -l) != l); 40 | return n; 41 | } 42 | template int min_left(int r, F f) const { 43 | if(!r) return 0; 44 | r += s; 45 | S sm = e(); 46 | do { 47 | r--; 48 | while(r > 1 and r & 1) r >>= 1; 49 | if(!f(op(d[r], sm))) { 50 | while(r < s) { 51 | r = (2 * r + 1); 52 | if(f(op(d[r], sm))) sm = op(d[r--], sm); 53 | } 54 | return r + 1 - s; 55 | } 56 | sm = op(d[r], sm); 57 | } while((r & -r) != r); 58 | return 0; 59 | } 60 | 61 | private: 62 | int n, s, log; 63 | vector d; 64 | void update(int k) { d[k] = op(d[k * 2], d[k * 2 + 1]); } 65 | }; -------------------------------------------------------------------------------- /src/data-structure/sparse-table-disjoint.hpp: -------------------------------------------------------------------------------- 1 | template struct sptable { 2 | const F f; 3 | vector> a; 4 | vi l; 5 | 6 | sptable(const vector& v, F f) : f(f) { 7 | int m = 0; 8 | while((1 << m) <= si(v)) ++m; 9 | a.resize(m, vector(si(v), T())); 10 | rep(i, si(v)) a[0][i] = v[i]; 11 | rep(i, 1, m) { 12 | int s = 1 << i; 13 | for(int j = 0; j < si(v); j += s * 2) { 14 | int t = min(j + s, si(v)); 15 | a[i][t - 1] = v[t - 1]; 16 | per(k, t - 1, j) a[i][k] = f(v[k], a[i][k + 1]); 17 | if(si(v) <= t) break; 18 | a[i][t] = v[t]; 19 | int r = min(t + s, si(v)); 20 | rep(k, t + 1, r) a[i][k] = f(a[i][k - 1], v[k]); 21 | } 22 | } 23 | l.resize(1 << m); 24 | rep(i, 2, si(l)) l[i] = l[i >> 1] + 1; 25 | } 26 | 27 | T query(int x, int y) { 28 | if(x >= --y) return a[0][x]; 29 | int p = l[x ^ y]; 30 | return f(a[p][x], a[p][y]); 31 | } 32 | }; -------------------------------------------------------------------------------- /src/data-structure/swag.hpp: -------------------------------------------------------------------------------- 1 | template struct SWAG { 2 | using vp = vector>; 3 | vp a, b; 4 | F f; 5 | T I; 6 | SWAG(F f, T i) : f(f), I(i) {} 7 | 8 | private: 9 | T get(vp& v) { return empty(v) ? I : v.back().second; } 10 | void pusha(T x) { a.eb(x, f(x, get(a))); } 11 | void pushb(T x) { b.eb(x, f(get(b), x)); } // reversed!! 12 | void rebalance() { 13 | int n = si(a) + si(b); 14 | int s0 = n / 2 + (empty(a) ? n & 1 : 0); 15 | vp v{a}; 16 | reverse(all(v)); 17 | copy(all(b), back_inserter(v)); 18 | a.clear(), b.clear(); 19 | per(i, s0, 0) pusha(v[i].first); 20 | rep(i, s0, n) pushb(v[i].first); 21 | } 22 | 23 | public: 24 | T front() { return (a.empty() ? b.front() : a.back()).first; } 25 | T back() { return (b.empty() ? a.front() : b.back()).first; } 26 | void pop_front() { 27 | if(empty(a)) rebalance(); 28 | a.pop_back(); 29 | } 30 | void pop_back() { 31 | if(empty(b)) rebalance(); 32 | b.pop_back(); 33 | } 34 | T query() { return f(get(a), get(b)); } 35 | }; -------------------------------------------------------------------------------- /src/data-structure/wavelet_matrix.hpp: -------------------------------------------------------------------------------- 1 | #define U uint32_t 2 | #define L uint64_t 3 | struct bit_vector { 4 | static constexpr U w = 64; 5 | vector block; 6 | vector count; 7 | int n, zeros; 8 | 9 | inline U get(U i) const { return U(block[i / w] >> (i % w)) & 1; } 10 | inline void set(U i) { block[i / w] |= 1LL << (i % w); } 11 | 12 | bit_vector() {} 13 | bit_vector(int n) { init(n); } 14 | void init(int _n) { 15 | n = zeros = _n; 16 | block.resize(n / w + 1, 0); 17 | count.resize(si(block), 0); 18 | } 19 | 20 | void build() { 21 | rep(i, 1, si(block)) count[i] = count[i - 1] + popcount(block[i - 1]); 22 | zeros = rank0(n); 23 | } 24 | 25 | inline U rank0(U i) const { return i - rank1(i); } 26 | inline U rank1(U i) const { return count[i / w] + popcount(block[i / w] & ((1ULL << i % w) - 1)); } 27 | }; 28 | 29 | template struct WaveletMatrix { 30 | int n; 31 | vector a; 32 | array bv; 33 | WaveletMatrix(const vector& _a) : n(_a.size()), a(_a) { build2(); } 34 | 35 | void build() { 36 | rep(i, lg) bv[i] = bit_vector(n); 37 | vector cur = a, nxt(n); 38 | per(h, lg, 0) { 39 | rep(i, n) if(cur[i] >> h & 1) bv[h].set(i); 40 | bv[h].build(); 41 | array it{begin(nxt), begin(nxt) + bv[h].zeros}; 42 | rep(i, n) * it[bv[h].get(i)]++ = cur[i]; 43 | swap(cur, nxt); 44 | } 45 | return; 46 | } 47 | 48 | inline pair succ0(int l, int r, int h) const { return make_pair(bv[h].rank0(l), bv[h].rank0(r)); } 49 | 50 | inline pair succ1(int l, int r, int h) const { 51 | U l0 = bv[h].rank0(l); 52 | U r0 = bv[h].rank0(r); 53 | U zeros = bv[h].zeros; 54 | return make_pair(l + zeros - l0, r + zeros - r0); 55 | } 56 | 57 | T access(U k) const { 58 | T ret = 0; 59 | per(h, lg, 0) { 60 | U f = bv[h].get(k); 61 | ret |= f ? T(1) << h : 0; 62 | k = f ? bv[h].rank1(k) + bv[h].zeros : bv[h].rank0(k); 63 | } 64 | return ret; 65 | } 66 | 67 | T kth_smallest(U l, U r, U k) const { 68 | T res = 0; 69 | for(int h = lg - 1; h >= 0; --h) { 70 | U l0 = bv[h].rank0(l), r0 = bv[h].rank0(r); 71 | if(k < r0 - l0) l = l0, r = r0; 72 | else { 73 | k -= r0 - l0; 74 | res |= (T)1 << h; 75 | l += bv[h].zeros - l0, r += bv[h].zeros - r0; 76 | } 77 | } 78 | return res; 79 | } 80 | T kth_largest(int l, int r, int k) { return kth_smallest(l, r, r - l - k - 1); } 81 | 82 | int range_freq(int l, int r, T upper) { 83 | if(upper >= (T(1) << lg)) return r - l; 84 | int ret = 0; 85 | per(h, lg, 0) { 86 | bool f = (upper >> h) & 1; 87 | U l0 = bv[h].rank0(l), r0 = bv[h].rank0(r); 88 | if(f) { 89 | ret += r0 - l0; 90 | l += bv[h].zeros - l0; 91 | r += bv[h].zeros - r0; 92 | } else { 93 | l = l0; 94 | r = r0; 95 | } 96 | } 97 | return ret; 98 | } 99 | int range_freq(int l, int r, T lower, T upper) { return range_freq(l, r, upper) - range_freq(l, r, lower); } 100 | 101 | array, lg> sums; 102 | vector acc; 103 | void build2() { 104 | rep(i, lg) bv[i] = bit_vector(n), sums[i].assign(n + 1, 0); 105 | acc.resize(si(a) + 1); 106 | vector cur = a, nxt(n); 107 | per(h, lg, 0) { 108 | rep(i, n) if((cur[i] >> h) & 1) bv[h].set(i); 109 | bv[h].build(); 110 | array it{begin(nxt), begin(nxt) + bv[h].zeros}; 111 | rep(i, n) * it[bv[h].get(i)]++ = cur[i]; 112 | swap(cur, nxt); 113 | rep(i, n) sums[h][i + 1] = sums[h][i] + cur[i]; 114 | } 115 | rep(i, n) acc[i + 1] = acc[i] + a[i]; 116 | } 117 | 118 | ll bottom_k_sum(int l, int r, int k) { 119 | ll res = 0; 120 | per(h, lg, 0) { 121 | U l0 = bv[h].rank0(l), r0 = bv[h].rank0(r); 122 | if(k < r0 - l0) { 123 | l = l0, r = r0; 124 | } else { 125 | res += sums[h][r0] - sums[h][l0]; 126 | k -= r0 - l0; 127 | l += bv[h].zeros - l0; 128 | r += bv[h].zeros - r0; 129 | } 130 | } 131 | res += sums[0][l + k] - sums[0][l]; 132 | return res; 133 | } 134 | 135 | ll top_k_sum(int l, int r, int k) { return acc[r] - acc[l] - bottom_k_sum(l, r, r - l - k); } 136 | }; 137 | #undef U 138 | #undef L -------------------------------------------------------------------------------- /src/dp/d-edge-monge.hpp: -------------------------------------------------------------------------------- 1 | template().get())> T incremental_monge_shortest_path(const int n, C init) { 2 | class env { 3 | public: 4 | C mid; 5 | C last; 6 | int prev; 7 | }; 8 | std::vector nodes; 9 | { 10 | int n_ = n; 11 | int d = 0; 12 | while(n_ != 0) { 13 | n_ /= 2; 14 | d += 1; 15 | } 16 | nodes.assign(d, {init, init, 0}); 17 | } 18 | std::vector dp(n + 1, static_cast(0)); 19 | 20 | const auto f = [&](const auto& f, const int d, const int r) -> int { 21 | auto& [mid, last, prev] = nodes[d]; 22 | const int w = 1 << d; 23 | if((r >> d) % 2 == 1) { 24 | for(int i = std::max(0, r - 2 * w); i != r; i += 1) { mid.push_back(i); } 25 | const int next = r + w <= n ? f(f, d + 1, r + w) : r - w; 26 | int argmin = prev; 27 | dp[r] = dp[argmin] + mid.get(); 28 | for(int i = prev; i != next;) { 29 | mid.pop_front(i); 30 | i += 1; 31 | const T t = dp[i] + mid.get(); 32 | if(dp[r] > t) { 33 | dp[r] = t; 34 | argmin = i; 35 | } 36 | } 37 | prev = next; 38 | return argmin; 39 | } else { 40 | for(int i = std::max(0, r - 2 * w); i != r; i += 1) { last.push_back(i); } 41 | for(int i = std::max(0, r - 3 * w); i != r - 2 * w; i += 1) { last.pop_front(i); } 42 | int argmin = prev; 43 | for(int i = r - 2 * w; i != r - w;) { 44 | last.pop_front(i); 45 | i += 1; 46 | const T t = dp[i] + last.get(); 47 | if(dp[r] > t) { 48 | dp[r] = t; 49 | argmin = i; 50 | } 51 | } 52 | return argmin; 53 | } 54 | }; 55 | 56 | for(int i = 1; i != n + 1; i += 1) { f(f, 0, i); } 57 | 58 | return dp[n]; 59 | } 60 | 61 | namespace golden_section_search_impl { 62 | 63 | using i64 = std::int64_t; 64 | 65 | template()(std::declval())), class Compare = std::less> 66 | std::pair golden_section_search(F f, i64 min, i64 max, Compare comp = Compare()) { 67 | assert(min <= max); 68 | 69 | i64 a = min - 1, x, b; 70 | { 71 | i64 s = 1, t = 2; 72 | while(t < max - min + 2) { std::swap(s += t, t); } 73 | x = a + t - s; 74 | b = a + t; 75 | } 76 | T fx = f(x), fy; 77 | while(a + b != 2 * x) { 78 | const i64 y = a + b - x; 79 | if(max < y || comp(fx, (fy = f(y)))) { 80 | b = a; 81 | a = y; 82 | } else { 83 | a = x; 84 | x = y; 85 | fx = fy; 86 | } 87 | } 88 | return {x, fx}; 89 | } 90 | 91 | } // namespace golden_section_search_impl 92 | 93 | using golden_section_search_impl::golden_section_search; 94 | 95 | struct cost { 96 | const vector* a; 97 | ll lambda; 98 | ll cost; 99 | void pop_front(int l) {} 100 | void push_back(int r) {} 101 | ll get() { return lambda + c } // 最小化なら - 102 | }; 103 | 104 | // k : 使う辺の本数 105 | const auto f = [&](ll l) -> ll { 106 | auto res = incremental_monge_shortest_path(n + 1, cost{l, 0, 0}) - l * (k + 1); 107 | return res; 108 | }; 109 | // L = - max(|e|) * 3, R = max(|e|) * 3 110 | OUT(golden_section_search(f, L, R, greater()).se); -------------------------------------------------------------------------------- /src/dp/mo-rollback.hpp: -------------------------------------------------------------------------------- 1 | 2 | struct MoRollBack { 3 | using ADD = function; 4 | using REM = function; 5 | using RESET = function; 6 | using SNAP = function; 7 | using ROLLBACK = function; 8 | int w; 9 | vector l, r, ord; 10 | MoRollBack(int n, int q) : w((int)sqrt(n)), ord(q) { iota(all(ord), 0); } 11 | void add(int a, int b) { /* [l, r) */ 12 | l.emplace_back(a); 13 | r.emplace_back(b); 14 | } 15 | void run(const ADD& add, const REM& rem, const RESET& reset, const SNAP& snap, const ROLLBACK& rollback) { 16 | sort(begin(ord), end(ord), [&](int a, int b) { 17 | int ab = l[a] / w, bb = l[b] / w; 18 | if(ab != bb) return ab < bb; 19 | return r[a] < r[b]; 20 | }); 21 | reset(); 22 | for(auto idx : ord) { 23 | if(r[idx] - l[idx] < w) { 24 | rep(i, l[idx], r[idx]) add(i); 25 | rem(idx); 26 | rollback(); 27 | } 28 | } 29 | int nr = 0, lb = -1; 30 | for(auto idx : ord) { 31 | if(r[idx] - l[idx] < w) continue; 32 | int b = l[idx] / w; 33 | if(lb != b) { 34 | reset(); 35 | lb = b; 36 | nr = (b + 1) * w; 37 | } 38 | while(nr < r[idx]) add(nr++); 39 | snap(); 40 | per(j, (b + 1) * w, l[idx]) add(j); 41 | rem(idx); 42 | rollback(); 43 | } 44 | } 45 | }; -------------------------------------------------------------------------------- /src/dp/mo.hpp: -------------------------------------------------------------------------------- 1 | struct Mo { 2 | int n; 3 | vector lr; 4 | Mo(int n) : n(n) {} 5 | void add(int l, int r) { lr.eb(l, r); } 6 | template 7 | void build(const AL& add_left, const AR& add_right, const EL& erase_left, const ER& erase_right, const O& out) { 8 | int q = (int)lr.size(); 9 | int bs = n / min(n, sqrt(q)); 10 | vector ord(q); 11 | iota(all(ord), 0); 12 | sort(all(ord), [&](int a, int b) { 13 | int ab = lr[a].first / bs, bb = lr[b].first / bs; 14 | if(ab != bb) return ab < bb; 15 | return (ab & 1) ? lr[a].second > lr[b].second : lr[a].second < lr[b].second; 16 | }); 17 | int l = 0, r = 0; 18 | for(auto idx : ord) { 19 | while(l > lr[idx].first) add_left(--l); 20 | while(r < lr[idx].second) add_right(r++); 21 | while(l < lr[idx].first) erase_left(l++); 22 | while(r > lr[idx].second) erase_right(--r); 23 | out(idx); 24 | } 25 | } 26 | template void build(const A& add, const E& erase, const O& out) { 27 | build(add, add, erase, erase, out); 28 | } 29 | }; -------------------------------------------------------------------------------- /src/dp/monge-incremental-rowmin.hpp: -------------------------------------------------------------------------------- 1 | 2 | // A[N + 1][N + 1]: Monge が i > j のみ存在しているとき、i (= 0, ..., N)行目の最小値を返す 3 | // f(i, j, v) で、j 行目の最小値が求まっている v を用いて、A[i][j] にアクセス 4 | template vector monge_rowmin(int n, const F& f) { 5 | vector mi(n + 1, numeric_limits::max()); 6 | mi[0] = 0; 7 | vector amin(n + 1); 8 | auto check = [&](int i, int j) { 9 | if(chmin(mi[i], f(i, j, mi))) { amin[i] = j; } 10 | }; 11 | check(n, 0); 12 | auto solve = [&](auto&& self, int l, int r) { 13 | if(r - l == 1) return; 14 | int mid = l + r >> 1; 15 | rep(k, amin[l], amin[r] + 1) check(mid, k); 16 | self(self, l, mid); 17 | rep(k, l + 1, mid + 1) check(r, k); 18 | self(self, mid, r); 19 | }; 20 | solve(solve, 0, n); 21 | return mi; 22 | } -------------------------------------------------------------------------------- /src/dp/monotone-minima.hpp: -------------------------------------------------------------------------------- 1 | 2 | // monotone 行列の各行について、最小値を取る場所とその値を返す 3 | template vector> monotone_minima(int h, int w, const F& f) { 4 | vector> dp(h, pair(-1, T())); 5 | auto rec = [&](auto&& rec, int u, int d, int l, int r) { 6 | if(u > d) return; 7 | int mid = u + d >> 1; 8 | auto& [idx, mi] = dp[mid]; 9 | idx = l, mi = f(mid, l); 10 | rep(i, l + 1, r + 1) if(chmin(mi, f(mid, i))) idx = i; 11 | rec(rec, u, mid - 1, l, idx); 12 | rec(rec, mid + 1, d, idx, r); 13 | }; 14 | rec(rec, 0, h - 1, 0, w - 1); 15 | return dp; 16 | } -------------------------------------------------------------------------------- /src/flow/bipartite-matching.hpp: -------------------------------------------------------------------------------- 1 | struct Bimatch { 2 | vector g; 3 | vi d, mc, used, vv; 4 | Bimatch(int n, int m) : g(n), mc(m, -1), used(n) {} 5 | void add(int u, int v) { g[u].eb(v); } 6 | void bfs() { 7 | d.assign(si(g), -1); 8 | queue q; 9 | rep(i, si(g)) { 10 | if(!used[i]) { 11 | q.emplace(i); 12 | d[i] = 0; 13 | } 14 | } 15 | while(!q.empty()) { 16 | int x = q.front(); 17 | q.pop(); 18 | fore(e, g[x]) { 19 | int c = mc[e]; 20 | if(c >= 0 and d[c] == -1) { 21 | d[c] = d[x] + 1; 22 | q.emplace(c); 23 | } 24 | } 25 | } 26 | } 27 | 28 | bool dfs(int x) { 29 | vv[x] = true; 30 | fore(e, g[x]) { 31 | int c = mc[e]; 32 | if(c < 0 or (!vv[c] and d[c] == d[x] + 1 and dfs(c))) { 33 | mc[e] = x; 34 | used[x] = true; 35 | return true; 36 | } 37 | } 38 | return false; 39 | } 40 | int match() { 41 | int ret = 0; 42 | while(true) { 43 | bfs(); 44 | vv.assign(si(g), false); 45 | int f = 0; 46 | rep(i, si(g)) if(!used[i] and dfs(i)) f++; 47 | if(!f) return ret; 48 | ret += f; 49 | } 50 | } 51 | }; -------------------------------------------------------------------------------- /src/flow/flow.hpp: -------------------------------------------------------------------------------- 1 | template struct Dinic { 2 | const T INF; 3 | 4 | struct edge { 5 | int to; 6 | T cap; 7 | int rev; 8 | bool isrev; 9 | int idx; 10 | }; 11 | 12 | vector> g; 13 | vector c, iter; 14 | Dinic(int V) : INF(numeric_limits::max()), g(V) {} 15 | void add_edge(int from, int to, T cap, int idx = -1) { 16 | g[from].emplace_back((edge){to, cap, si(g[to]), false, idx}); 17 | g[to].emplace_back((edge){from, 0, si(g[from]) - 1, true, idx}); 18 | } 19 | 20 | bool bfs(int s, int t) { 21 | c.assign(si(g), -1); 22 | queue q; 23 | c[s] = 0; 24 | q.push(s); 25 | while(!q.empty() && c[t] == -1) { 26 | int x = q.front(); 27 | q.pop(); 28 | fore(e, g[x]) { 29 | if(e.cap > 0 && c[e.to] == -1) { 30 | c[e.to] = c[x] + 1; 31 | q.push(e.to); 32 | } 33 | } 34 | } 35 | return c[t] != -1; 36 | } 37 | 38 | T dfs(int x, int t, T flow) { 39 | if(x == t) return flow; 40 | for(int& i = iter[x]; i < si(g[x]); i++) { 41 | edge& e = g[x][i]; 42 | if(e.cap > 0 && c[x] < c[e.to]) { 43 | T d = dfs(e.to, t, min(flow, e.cap)); 44 | if(d > 0) { 45 | e.cap -= d; 46 | g[e.to][e.rev].cap += d; 47 | return d; 48 | } 49 | } 50 | } 51 | return 0; 52 | } 53 | 54 | T max_flow(int s, int t) { 55 | T flow = 0; 56 | while(bfs(s, t)) { 57 | iter.assign(si(g), 0); 58 | T f = 0; 59 | while((f = dfs(s, t, INF)) > 0) flow += f; 60 | } 61 | return flow; 62 | } 63 | 64 | // void output() { 65 | // for(int i = 0; i < g.size(); i++) { 66 | // for(auto &e : g[i]) { 67 | // if(e.isrev) continue; 68 | // auto &rev_e = g[e.to][e.rev]; 69 | // cout << i << "->" << e.to << " (flow: " << rev_e.cap << "/" << e.cap + rev_e.cap << ")" << endl; 70 | // } 71 | // } 72 | // } 73 | }; 74 | -------------------------------------------------------------------------------- /src/flow/lower-upper-bound-flow.hpp: -------------------------------------------------------------------------------- 1 | template struct lrFlow { 2 | Dinic flow; 3 | vector in, up; 4 | int X, Y, n; 5 | T sum; 6 | typename Dinic::edge *p, *q; 7 | 8 | lrFlow(int n) : n(n), X(n), Y(n + 1), sum(0), in(n), flow(n + 2) {} 9 | 10 | void add_edge(int from, int to, T low, T high) { 11 | flow.add_edge(from, to, high - low, si(up)); 12 | in[from] -= low, in[to] += low; 13 | up.eb(high); 14 | } 15 | 16 | void build() { 17 | rep(i, n) { 18 | if(in[i] > 0) { 19 | flow.add_edge(X, i, in[i]); 20 | sum += in[i]; 21 | } else if(in[i] < 0) { 22 | flow.add_edge(i, Y, -in[i]); 23 | } 24 | } 25 | } 26 | 27 | bool can_flow(int s, int t) { 28 | flow.add_edge(t, s, flow.INF); 29 | p = &flow.g[t].back(); 30 | q = &flow.g[s].back(); 31 | return can_flow(); 32 | } 33 | 34 | bool can_flow() { 35 | build(); 36 | auto ret = flow.max_flow(X, Y); 37 | return ret >= sum; 38 | } 39 | 40 | T max_flow(int s, int t) { 41 | if(can_flow(s, t)) { 42 | return flow.max_flow(s, t); 43 | } else { 44 | return -1; 45 | } 46 | } 47 | 48 | T min_flow(int s, int t) { 49 | if(can_flow(s, t)) { 50 | auto ret = flow.INF - p->cap; 51 | p->cap = q->cap = 0; 52 | return ret - flow.max_flow(t, s); 53 | } else { 54 | return -1; 55 | } 56 | } 57 | 58 | // void output(int M) { 59 | // vector ans(M); 60 | // for(int i = 0; i < flow.graph.size(); i++) { 61 | // for(auto &e : flow.graph[i]) { 62 | // if(!e.isrev && ~e.idx) ans[e.idx] = up[e.idx] - e.cap; 63 | // } 64 | // } 65 | // for(auto &p : ans) cout << p << endl; 66 | // } 67 | }; 68 | -------------------------------------------------------------------------------- /src/flow/mcf.hpp: -------------------------------------------------------------------------------- 1 | 2 | struct MCF { 3 | struct edge { 4 | int to; 5 | ll cap, cost; 6 | int rev; 7 | bool isrev; 8 | }; 9 | vector> g; 10 | vl pot, cost; 11 | vi pv, pe; 12 | MCF(int n) : g(n) {} 13 | void add(int u, int v, ll cap, ll cost) { 14 | g[u].eb(v, cap, cost, si(g[v]), false); 15 | g[v].eb(u, 0, -cost, si(g[u]) - 1, true); 16 | } 17 | ll mcf(int s, int t, ll f) { 18 | int n = si(g); 19 | ll ret = 0; 20 | using P = pair; 21 | priority_queue, greater

    > pq; 22 | pot.assign(n, 0), pe.assign(n, -1), pv.assign(n, -1); 23 | while(f) { 24 | cost.assign(n, INFL); 25 | pq.emplace(0, s); 26 | cost[s] = 0; 27 | while(!pq.empty()) { 28 | auto [c, x] = pq.top(); 29 | pq.pop(); 30 | if(cost[x] < c) continue; 31 | rep(i, si(g[x])) { 32 | edge& e = g[x][i]; 33 | ll ncost = cost[x] + e.cost + pot[x] - pot[e.to]; 34 | if(e.cap and chmin(cost[e.to], ncost)) { 35 | pv[e.to] = x, pe[e.to] = i; 36 | pq.emplace(cost[e.to], e.to); 37 | } 38 | } 39 | } 40 | if(cost[t] == INFL) return -1; 41 | rep(i, n) pot[i] += cost[i]; 42 | ll addflow = f; 43 | for(int v = t; v != s; v = pv[v]) chmin(addflow, g[pv[v]][pe[v]].cap); 44 | f -= addflow; 45 | ret += addflow * pot[t]; 46 | for(int v = t; v != s; v = pv[v]) { 47 | auto& e = g[pv[v]][pe[v]]; 48 | e.cap -= addflow; 49 | g[v][e.rev].cap += addflow; 50 | } 51 | } 52 | return ret; 53 | } 54 | }; -------------------------------------------------------------------------------- /src/flow/二部グラフ.md: -------------------------------------------------------------------------------- 1 | | | サイズ | 構成| 2 | |最大マッチング| $|M|$ | | 3 | |最小点被覆| $|M|$ | L到達不可能 + R到達可能| 4 | |最大安定集合| $|V| - |M|$ | 上の補グラフ| 5 | |最小辺被覆| 孤立点がないなら $|V| - |M|$ | 最大マッチング + 含まれない点 greedy| -------------------------------------------------------------------------------- /src/flow/燃やす埋める.md: -------------------------------------------------------------------------------- 1 | | 変形前の制約 | 変形後の制約 | 2 | | --- | --- | 3 | | $x$ が $0$ のとき $z$ 失う | $(x, T, z)$ | 4 | | $x$ が $0$ のとき $z$ 得る | 無条件で $z$ 得る; $(S, x, z)$ | 5 | | $x$ が $1$ のとき $z$ 失う | $(S, x, z)$ | 6 | | $x$ が $1$ のとき $z$ 得る | 無条件で $z$ 得る; $(x, T, z)$ | 7 | | $x, y, \dots$ がすべて $0$ のとき $z$ 得る | 無条件で $z$ 得る; $(S, w, z), (w, x, \infty), (w, y, \infty)$ | 8 | | $x, y, \dots$ がすべて $1$ のとき $z$ 得る | 無条件で $z$ 得る; $(w, T, z), (x, w, \infty), (y, w, \infty)$ | 9 | -------------------------------------------------------------------------------- /src/geometry/argument-sort.hpp: -------------------------------------------------------------------------------- 1 | bool operator<(point P, point Q) { 2 | long long C = cross(P, Q); 3 | if(C == 0 && dot(P, Q) > 0) { 4 | return false; 5 | } else if(P.x < 0 && P.y == 0) { 6 | return true; 7 | } else if(Q.x < 0 && Q.y == 0) { 8 | return false; 9 | } else if(P.y * Q.y <= 0) { 10 | return P.y < Q.y; 11 | } else { 12 | return C > 0; 13 | } 14 | } -------------------------------------------------------------------------------- /src/geometry/circle.hpp: -------------------------------------------------------------------------------- 1 | struct circle { 2 | point C; 3 | double r; 4 | circle() {} 5 | circle(point C, double r) : C(C), r(r) {} 6 | }; 7 | pair line_circle_intersection(line L, circle C) { 8 | point P = projection(C.C, L); 9 | double d = point_line_distance(C.C, L); 10 | double h = sqrt(C.r * C.r - d * d); 11 | point A = P + vec(L) / abs(vec(L)) * h; 12 | point B = P - vec(L) / abs(vec(L)) * h; 13 | return make_pair(A, B); 14 | } 15 | pair circle_intersection(circle C1, circle C2) { 16 | double d = dist(C1.C, C2.C); 17 | double m = (C1.r * C1.r - C2.r * C2.r + d * d) / (d * 2); 18 | point M = C1.C + (C2.C - C1.C) / d * m; 19 | double h = sqrt(C1.r * C1.r - m * m); 20 | point H = rotate90(C2.C - C1.C) / d * h; 21 | return make_pair(M - H, M + H); 22 | } 23 | pair circle_tangent(point P, circle C) { 24 | double d = dist(P, C.C); 25 | double r = sqrt(d * d - C.r * C.r); 26 | return circle_intersection(C, circle(P, r)); 27 | } 28 | vector common_tangent(circle C1, circle C2) { 29 | if(C1.r < C2.r) { swap(C1, C2); } 30 | double d = dist(C1.C, C2.C); 31 | vector L; 32 | if(C1.r - C2.r <= d + eps) { 33 | if(C1.r - C2.r <= eps) { 34 | point D = rotate90(C2.C - C1.C) / d * C1.r; 35 | L.push_back(line(C1.C + D, C2.C + D)); 36 | L.push_back(line(C1.C - D, C2.C - D)); 37 | } else { 38 | double m = (C1.r - C2.r) * (C1.r - C2.r) / d; 39 | point M = C1.C + (C2.C - C1.C) / d * m; 40 | double h = sqrt((C1.r - C2.r) * (C1.r - C2.r) - m * m); 41 | point H1 = M + rotate90(C2.C - C1.C) / d * h; 42 | point D1 = (H1 - C1.C) / dist(H1, C1.C) * C2.r; 43 | L.push_back(line(H1 + D1, C2.C + D1)); 44 | point H2 = M - rotate90(C2.C - C1.C) / d * h; 45 | point D2 = (H2 - C1.C) / dist(H2, C1.C) * C2.r; 46 | L.push_back(line(H2 + D2, C2.C + D2)); 47 | } 48 | } 49 | if(C1.r + C2.r <= d + eps) { 50 | double m = (C1.r + C2.r) * (C1.r + C2.r) / d; 51 | point M = C1.C + (C2.C - C1.C) / d * m; 52 | double h = sqrt((C1.r + C2.r) * (C1.r + C2.r) - m * m); 53 | point H1 = M + rotate90(C2.C - C1.C) / d * h; 54 | point D1 = (H1 - C1.C) / dist(H1, C1.C) * C2.r; 55 | L.push_back(line(H1 - D1, C2.C - D1)); 56 | point H2 = M - rotate90(C2.C - C1.C) / d * h; 57 | point D2 = (H2 - C1.C) / dist(H2, C1.C) * C2.r; 58 | L.push_back(line(H2 - D2, C2.C - D2)); 59 | } 60 | return L; 61 | } -------------------------------------------------------------------------------- /src/geometry/convex-hull.hpp: -------------------------------------------------------------------------------- 1 | Points convex_hull(Points& p) { 2 | int n = p.size(), k = 0; 3 | if(n <= 2) return p; 4 | sort(begin(p), end(p), [](pt x, pt y) { return (x.x != y.x ? x.x < y.x : x.y < y.y); }); 5 | Points ch(2 * n); 6 | for(int i = 0; i < n; ch[k++] = p[i++]) { 7 | while(k >= 2 && cross(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) <= 0) --k; 8 | } 9 | for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--]) { 10 | while(k >= t && cross(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) <= 0) --k; 11 | } 12 | ch.resize(k - 1); 13 | return ch; 14 | } -------------------------------------------------------------------------------- /src/geometry/funcs.hpp: -------------------------------------------------------------------------------- 1 | int contains(const Polygon& Q, const Point& p) { 2 | bool in = false; 3 | for(int i = 0; i < Q.size(); i++) { 4 | Point a = Q[i] - p, b = Q[(i + 1) % Q.size()] - p; 5 | if(a.y > b.y) swap(a, b); 6 | if(a.y <= 0 && 0 < b.y && cross(a, b) < 0) in = !in; 7 | if(cross(a, b) == 0 && dot(a, b) <= 0) return _ON; 8 | } 9 | return in ? _IN : _OUT; 10 | } 11 | 12 | Polygon Minkowski_sum(const Polygon& P, const Polygon& Q) { 13 | vector e1(P.size()), e2(Q.size()), ed(P.size() + Q.size()); 14 | const auto cmp = [](const Segment& u, const Segment& v) { return (u.b - u.a).arg_cmp(v.b - v.a); }; 15 | rep(i, P.size()) e1[i] = {P[i], P[(i + 1) % P.size()]}; 16 | rep(i, Q.size()) e2[i] = {Q[i], Q[(i + 1) % Q.size()]}; 17 | rotate(begin(e1), min_element(all(e1), cmp), end(e1)); 18 | rotate(begin(e2), min_element(all(e2), cmp), end(e2)); 19 | merge(all(e1), all(e2), begin(ed), cmp); 20 | const auto check = [](const Points& res, const Point& u) { 21 | const auto back1 = res.back(), back2 = *prev(end(res), 2); 22 | return eq(cross(back1 - back2, u - back2), eps) and dot(back1 - back2, u - back1) >= -eps; 23 | }; 24 | auto u = e1[0].a + e2[0].a; 25 | Points res{u}; 26 | res.reserve(P.size() + Q.size()); 27 | for(const auto& v : ed) { 28 | u = u + v.b - v.a; 29 | while(si(res) >= 2 and check(res, u)) res.pop_back(); 30 | res.eb(u); 31 | } 32 | if(res.size() and check(res, res[0])) res.pop_back(); 33 | return res; 34 | } 35 | 36 | // -1 : on, 0 : out, 1 : in 37 | // O(log(n)) 38 | bool is_in(const Polygon& p, const Point& a) { 39 | if(p.size() == 1) return a == p[0] ? -1 : 0; 40 | if(p.size() == 2) return intersect(Segment(p[0], p[1]), a); 41 | if(a == p[0]) return -1; 42 | if((p[1] - p[0]).toleft(a - p[0]) == -1 || (p.back() - p[0]).toleft(a - p[0]) == 1) return 0; 43 | const auto cmp = [&](const Point& u, const Point& v) { return (u - p[0]).toleft(v - p[0]) == 1; }; 44 | const size_t i = lower_bound(p.begin() + 1, p.end(), a, cmp) - p.begin(); 45 | if(i == 1) return intersect(Segment(p[0], p[i]), a) ? -1 : 0; 46 | if(i == p.size() - 1 && intersect(Segment(p[0], p[i]), a)) return -1; 47 | if(intersect(Segment(p[i - 1], p[i]), a)) return -1; 48 | return (p[i] - p[i - 1]).toleft(a - p[i - 1]) > 0; 49 | } 50 | 51 | using speP = pair; 52 | struct ccut { 53 | private: 54 | set ags; 55 | vector nexs; 56 | vector pres; 57 | vector ps; 58 | 59 | public: 60 | void init() { 61 | const ld sup = -100000; 62 | ps.push_back({-sup, -sup}); 63 | ps.push_back({sup, -sup}); 64 | ps.push_back({sup, sup}); 65 | ps.push_back({-sup, sup}); 66 | nexs.resize(4); 67 | pres.resize(4); 68 | rep(i, 4) { 69 | int ni = (i + 1) % 4; 70 | Point dif = ps[ni] - ps[i]; 71 | ld t = arg(dif); 72 | ags.insert({t, i}); 73 | nexs[i] = ni; 74 | pres[ni] = i; 75 | } 76 | } 77 | void convex_cut(Point a, Point b) { 78 | if(ags.empty()) return; 79 | Point dif = b - a; 80 | ld t = arg(dif); 81 | auto itr = ags.lower_bound({t, -1}); 82 | if(itr == ags.end()) itr = ags.begin(); 83 | int cur = (*itr).second; 84 | if(ccw(a, b, ps[cur]) != -1) return; 85 | int ricur = nexs[cur]; 86 | while(ricur != cur && ccw(a, b, ps[ricur]) != 1) { ricur = nexs[ricur]; } 87 | if(ricur == cur) { 88 | ags.clear(); 89 | return; 90 | } 91 | int lecur = pres[cur]; 92 | while(ccw(a, b, ps[lecur]) != 1) { lecur = pres[lecur]; } 93 | // new point 94 | Line l = {a, b}; 95 | Line l1 = {ps[lecur], ps[nexs[lecur]]}; 96 | Line l2 = {ps[pres[ricur]], ps[ricur]}; 97 | Point p1 = is_ll(l1, l); 98 | Point p2 = is_ll(l2, l); 99 | int id1 = ps.size(); 100 | int id2 = ps.size() + 1; 101 | ps.push_back(p1), ps.push_back(p2); 102 | rep(2) nexs.push_back(-1), pres.push_back(-1); 103 | 104 | // erase(lecur,ricur) 105 | cur = lecur; 106 | int tmp = 0; 107 | while(cur != ricur || !tmp) { 108 | Point dif = ps[nexs[cur]] - ps[cur]; 109 | ld t = arg(dif); 110 | ags.erase({t, cur}); 111 | cur = nexs[cur]; 112 | tmp++; 113 | } 114 | 115 | nexs[lecur] = id1, pres[id1] = lecur, nexs[id1] = id2; 116 | pres[id2] = id1, nexs[id2] = ricur, pres[ricur] = id2; 117 | cur = lecur, tmp = 0; 118 | while(cur != ricur || !tmp) { 119 | Point dif = ps[nexs[cur]] - ps[cur]; 120 | ld t = arg(dif); 121 | ags.insert({t, cur}); 122 | cur = nexs[cur]; 123 | tmp++; 124 | } 125 | } 126 | polygon nw_poly() { 127 | polygon nw; 128 | for(auto p : ags) nw.push_back(ps[p.second]); 129 | return nw; 130 | } 131 | ld calc_area() { 132 | polygon nw; 133 | for(auto p : ags) nw.push_back(ps[p.second]); 134 | return area(nw); 135 | } 136 | }; -------------------------------------------------------------------------------- /src/geometry/line.hpp: -------------------------------------------------------------------------------- 1 | bool point_on_segment(point P, line L) { return dot(P - L.A, vec(L)) > -eps && dot(P - L.B, vec(L)) < eps; } 2 | point projection(point P, line L) { return L.A + vec(L) / abs(vec(L)) * dot(P - L.A, vec(L)) / abs(vec(L)); } 3 | point reflection(point P, line L) { return projection(P, L) * 2 - P; } 4 | double point_line_distance(point P, line L) { return abs(cross(P - L.A, vec(L))) / abs(vec(L)); } 5 | double point_segment_distance(point P, line L) { 6 | if(dot(P - L.A, vec(L)) < 0) { 7 | return dist(P, L.A); 8 | } else if(dot(P - L.B, vec(L)) > 0) { 9 | return dist(P, L.B); 10 | } else { 11 | return point_line_distance(P, L); 12 | } 13 | } 14 | bool is_parallel(line L1, line L2) { return abs(cross(vec(L1), vec(L2))) < eps; } 15 | point line_intersection(line L1, line L2) { 16 | return L1.A + vec(L1) * cross(L2.A - L1.A, vec(L2)) / cross(vec(L1), vec(L2)); 17 | } 18 | bool segment_intersect(line L1, line L2) { 19 | return cross(L1.A - L2.A, vec(L2)) * cross(L1.B - L2.A, vec(L2)) < eps 20 | && cross(L2.A - L1.A, vec(L1)) * cross(L2.B - L1.A, vec(L1)) < eps; 21 | } 22 | double segment_distance(line L1, line L2) { 23 | if(segment_intersect(L1, L2)) { 24 | return 0; 25 | } else { 26 | double ans = INF; 27 | ans = min(ans, point_segment_distance(L1.A, L2)); 28 | ans = min(ans, point_segment_distance(L1.B, L2)); 29 | ans = min(ans, point_segment_distance(L2.A, L1)); 30 | ans = min(ans, point_segment_distance(L2.B, L1)); 31 | return ans; 32 | } 33 | } -------------------------------------------------------------------------------- /src/graph/bcc.hpp: -------------------------------------------------------------------------------- 1 | template struct BCC : LL { 2 | vi used; 3 | vector> bc; 4 | vector tmp; 5 | using L = LL; 6 | using L::g; 7 | using L::low; 8 | using L::ord; 9 | 10 | BCC(G g) : L(g) { build(); } 11 | 12 | void build() { 13 | used.assign(si(g), 0); 14 | rep(i, si(used)) if(!used[i]) dfs(i, -1); 15 | } 16 | 17 | void dfs(int x, int p) { 18 | used[x] = true; 19 | fore(e, g[x]) { 20 | if(e == p) continue; 21 | if(!used[e] || ord[e] < ord[x]) tmp.eb(minmax(x, e)); 22 | if(!used[e]) { 23 | dfs(e, x); 24 | if(low[e] >= ord[x]) { 25 | bc.eb(); 26 | while(true) { 27 | auto p = tmp.back(); 28 | bc.back().eb(p); 29 | tmp.pop_back(); 30 | if(p.first == min(x, e) and p.second == max(x, e)) break; 31 | } 32 | } 33 | } 34 | } 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /src/graph/eulerian-trail.hpp: -------------------------------------------------------------------------------- 1 | struct edge { 2 | int x, y, idx; 3 | }; 4 | vector eulerian_path(vector es, int s, bool directed = false) { 5 | if(es.empty()) return {}; 6 | int n = 0; 7 | fore(e, es) chmax(n, max(e.x, e.y) + 1); 8 | vector>> g(n); 9 | for(auto& e : es) { 10 | int p = si(g[e.y]); 11 | g[e.x].emplace_back(e, p); 12 | if(!directed) { 13 | int q = si(g[e.x]) - 1; 14 | swap(e.x, e.y); 15 | g[e.x].emplace_back(e, q); 16 | } 17 | } 18 | vector ord; 19 | stack> st; 20 | st.emplace(s, edge{-1, -1, -1}); 21 | while(st.size()) { 22 | int x = st.top().first; 23 | if(empty(g[x])) { 24 | ord.eb(st.top().second); 25 | st.pop(); 26 | } else { 27 | auto e = g[x].back(); 28 | g[x].pop_back(); 29 | if(e.second == -1) continue; 30 | if(!directed) g[e.first.y][e.second].second = -1; 31 | st.emplace(e.first.y, e.first); 32 | } 33 | } 34 | ord.pop_back(); 35 | reverse(begin(ord), end(ord)); 36 | if(si(ord) != si(es)) return {}; 37 | return ord; 38 | } -------------------------------------------------------------------------------- /src/graph/lowlink.hpp: -------------------------------------------------------------------------------- 1 | template struct LL { 2 | int n; 3 | const G g; 4 | vi ord, low, arti; 5 | vector bridge; 6 | 7 | LL(G g) : n(si(g)), g(g), ord(si(g), -1), low(si(g), -1) { 8 | int k = 0; 9 | rep(i, n) { 10 | if(ord[i] == -1) k = dfs(i, k, -1); 11 | } 12 | } 13 | 14 | int dfs(int x, int k, int p) { 15 | low[x] = (ord[x] = k++); 16 | int cnt = 0; 17 | bool is_arti = false, second = false; 18 | fore(e, g[x]) { 19 | if(ord[e] == -1) { 20 | cnt++; 21 | k = dfs(e, k, x); 22 | chmin(low[x], low[e]); 23 | is_arti |= (p != -1) && (low[e] >= ord[x]); 24 | if(ord[x] < low[e]) bridge.eb(minmax(x, e)); 25 | } else if(e != p or second) { 26 | chmin(low[x], ord[e]); 27 | } else { 28 | second = true; 29 | } 30 | } 31 | is_arti |= p == -1 && cnt > 1; 32 | if(is_arti) arti.eb(x); 33 | return k; 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /src/graph/max_matching.hpp: -------------------------------------------------------------------------------- 1 | struct Matching { 2 | int n; 3 | vector g; 4 | vi mt; 5 | vi is_ev, gr_buf; 6 | vector nx; 7 | int st; 8 | int group(int x) { 9 | if(gr_buf[x] == -1 || is_ev[gr_buf[x]] != st) return gr_buf[x]; 10 | return gr_buf[x] = group(gr_buf[x]); 11 | } 12 | void match(int p, int b) { 13 | int d = mt[p]; 14 | mt[p] = b; 15 | if(d == -1 || mt[d] != p) return; 16 | if(nx[p].second == -1) { 17 | mt[d] = nx[p].first; 18 | match(nx[p].first, d); 19 | } else { 20 | match(nx[p].first, nx[p].second); 21 | match(nx[p].second, nx[p].first); 22 | } 23 | } 24 | bool arg() { 25 | is_ev[st] = st; 26 | gr_buf[st] = -1; 27 | nx[st] = pii(-1, -1); 28 | queue q; 29 | q.push(st); 30 | while(q.size()) { 31 | int a = q.front(); 32 | q.pop(); 33 | for(auto b : g[a]) { 34 | if(b == st) continue; 35 | if(mt[b] == -1) { 36 | mt[b] = a; 37 | match(a, b); 38 | return true; 39 | } 40 | if(is_ev[b] == st) { 41 | int x = group(a), y = group(b); 42 | if(x == y) continue; 43 | int z = -1; 44 | while(x != -1 || y != -1) { 45 | if(y != -1) swap(x, y); 46 | if(nx[x] == pii(a, b)) { 47 | z = x; 48 | break; 49 | } 50 | nx[x] = pii(a, b); 51 | x = group(nx[mt[x]].first); 52 | } 53 | for(int v : {group(a), group(b)}) { 54 | while(v != z) { 55 | q.push(v); 56 | is_ev[v] = st; 57 | gr_buf[v] = z; 58 | v = group(nx[mt[v]].first); 59 | } 60 | } 61 | } else if(is_ev[mt[b]] != st) { 62 | is_ev[mt[b]] = st; 63 | nx[b] = pii(-1, -1); 64 | nx[mt[b]] = pii(a, -1); 65 | gr_buf[mt[b]] = b; 66 | q.push(mt[b]); 67 | } 68 | } 69 | } 70 | return false; 71 | } 72 | Matching(const vector& _g) : n(int(_g.size())), g(_g), mt(n, -1), is_ev(n, -1), gr_buf(n), nx(n) { 73 | for(st = 0; st < n; st++) 74 | if(mt[st] == -1) arg(); 75 | } 76 | vector max_match() { 77 | vector res; 78 | rep(i, n) if(i < mt[i]) res.eb(i, mt[i]); 79 | return res; 80 | } 81 | }; -------------------------------------------------------------------------------- /src/graph/maximum-independent-set.hpp: -------------------------------------------------------------------------------- 1 | unsigned ll maximum_independent_set(vector g) { 2 | using U = unsigned long long; 3 | int n = si(g); 4 | vector nbd(n); 5 | rep(i, n) fore(e, g[i]) nbd[i] |= 1ULL << e; 6 | int best = 0; 7 | U res = 0; 8 | auto dfs = [&](auto&& dfs, U now, U rest) -> void { 9 | pii p(-1, -1); 10 | while(true) { 11 | bool upd = 0; 12 | rep(v, n) { 13 | if(rest >> v & 1) { 14 | int d = popcount(nbd[v] & rest); 15 | if(chmax(p.second, d)) p.first = v; 16 | if(d <= 1) rest ^= 1ULL << v, rest &= ~nbd[v], now |= 1ULL << v, upd = 1; 17 | } 18 | } 19 | if(!upd) break; 20 | p = {-1, -1}; 21 | } 22 | int a = popcount(now), b = popcount(rest); 23 | if(chmax(best, a)) res = now; 24 | if(!b or a + b <= best) return; 25 | int v = p.first; 26 | rest &= ~(1ULL << v); 27 | if(p.second >= 3) dfs(dfs, now, rest); 28 | now |= 1ULL << v; 29 | dfs(dfs, now, rest & ~(nbd[v])); 30 | }; 31 | U now = 0, rest = (1ULL << n) - 1; 32 | dfs(dfs, now, rest); 33 | return res; 34 | } -------------------------------------------------------------------------------- /src/graph/scc.hpp: -------------------------------------------------------------------------------- 1 | template struct SCC { 2 | G g; 3 | vector rg; 4 | vi comp, ord, used; 5 | int num; // 連結成分の数 6 | 7 | SCC(G g) : g(g), rg(si(g)), comp(si(g), -1), ord(si(g)), used(si(g)) { 8 | rep(i, si(g)) fore(e, g[i]) rg[e].eb(i); 9 | build(); 10 | }; 11 | int operator[](int k) { return comp[k]; } 12 | void dfs(int x) { 13 | if(used[x]) return; 14 | used[x] = true; 15 | fore(e, g[x]) if(!used[e]) dfs(e); 16 | ord.eb(x); 17 | } 18 | void rdfs(int x, int cnt) { 19 | if(comp[x] != -1) return; 20 | comp[x] = cnt; 21 | fore(e, rg[x]) if(comp[e] == -1) rdfs(e, cnt); 22 | } 23 | void build() { 24 | rep(i, g.size()) dfs(i); 25 | reverse(all(ord)); 26 | num = 0; 27 | fore(i, ord) if(comp[i] == -1) { rdfs(i, num), num++; } 28 | } 29 | }; -------------------------------------------------------------------------------- /src/graph/tecc.hpp: -------------------------------------------------------------------------------- 1 | template struct TCC : LL { 2 | using L = LL; 3 | using L::bridge; 4 | using L::g; 5 | using L::low; 6 | using L::ord; 7 | vi cmp; 8 | vector tree, group; 9 | void build() { 10 | cmp.assign(si(g), -1); 11 | int k = 0; 12 | rep(i, si(cmp)) if(cmp[i] == -1) dfs(i, -1, k); 13 | group.resize(k); 14 | rep(i, si(g)) group[cmp[i]].eb(i); 15 | tree.resize(k); 16 | for(auto [a, b] : bridge) { 17 | tree[cmp[a]].eb(cmp[b]); 18 | tree[cmp[b]].eb(cmp[a]); 19 | } 20 | } 21 | TCC(const G& g) : L(g) { build(); } 22 | void dfs(int x, int p, int& k) { 23 | if(p >= 0 and ord[p] >= low[x]) cmp[x] = cmp[p]; 24 | else cmp[x] = k++; 25 | fore(e, g[x]) if(cmp[e] == -1) dfs(e, x, k); 26 | } 27 | }; -------------------------------------------------------------------------------- /src/math/ExtGCD.hpp: -------------------------------------------------------------------------------- 1 | // returns gcd(a, b) and assign x, y to integers 2 | // s.t. ax + by = gcd(a, b) and |x| + |y| is minimized 3 | ll extgcd(ll a, ll b, ll& x, ll& y) { 4 | // assert(a >= 0 && b >= 0); 5 | if(!b) return x = 1, y = 0, a; 6 | ll d = extgcd(b, a % b, y, x); 7 | y -= a / b * x; 8 | return d; 9 | } 10 | ll inv_mod(ll x, ll md) { 11 | ll y, z; 12 | extgcd(x, md, y, z); 13 | return (y % md + md) % md; 14 | } -------------------------------------------------------------------------------- /src/math/and-or-convolution.hpp: -------------------------------------------------------------------------------- 1 | // and / or convolution 2 | template void fzt(vector& a, bool inv = false) { 3 | int n = si(a); 4 | int m = __lg(n); 5 | rep(i, m) { 6 | rep(b, n) { 7 | if((b >> i & 1) == isOR) a[b] += a[b ^ 1 << i] * (inv ? -1 : 1); 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /src/math/binom.hpp: -------------------------------------------------------------------------------- 1 | constexpr int N = 1e6 + 100; 2 | mint fact[N], ifact[N]; 3 | void pre() { 4 | fact[0] = 1; 5 | rep(i, 1, N) fact[i] = i * fact[i - 1]; 6 | ifact[N - 1] = fact[N - 1].inv(); 7 | per(i, N - 1, 0) ifact[i] = ifact[i + 1] * (i + 1); 8 | } 9 | mint C(int n, int m) { return (n < m or m < 0 ? 0 : fact[n] * ifact[m] * ifact[n - m]); } 10 | -------------------------------------------------------------------------------- /src/math/crt.hpp: -------------------------------------------------------------------------------- 1 | // (rem, mod) 2 | pll crt(const vl& b, const vl& c) { 3 | int n = si(b); 4 | ll r = 0, m = 1; 5 | rep(i, n) { 6 | ll g, im, x; 7 | g = extgcd(m, c[i], im, x); 8 | if((b[i] - r) % g) return {0, -1}; 9 | ll tmp = (b[i] - r) / g * im % (c[i] / g); 10 | r += m * tmp; 11 | m *= c[i] / g; 12 | } 13 | return {(r % m + m) % m, m}; 14 | } -------------------------------------------------------------------------------- /src/math/floor_sum.hpp: -------------------------------------------------------------------------------- 1 | // x_i=floor((a*i+b)/c), i=0,1,..n-1 2 | // a,c>0, b>=0 3 | ll floor_sum(ll n, ll a, ll b, ll c) { 4 | if(n == 0) return 0; 5 | ll res = 0; 6 | res += n * (n - 1) / 2 * (a / c); 7 | a %= c; 8 | res += n * (b / c); 9 | b %= c; 10 | if(a == 0) return res; 11 | ll top = (a * (n - 1) + b) / c; 12 | res += top * n; 13 | ll h = (b + 1 + c - 1) / c; 14 | if(h <= top) res -= floor_sum(top - h + 1, c, c * h - (b + 1), a) + top - h + 1; 15 | return res; 16 | } -------------------------------------------------------------------------------- /src/math/lagrange-hokan.hpp: -------------------------------------------------------------------------------- 1 | template T lagrange_polynomial(const vector& y, ll t) { 2 | int n = si(y) - 1; 3 | if(t <= n) return y[t]; 4 | T ret(0); 5 | vector dp(n + 1, 1), pd(n + 1, 1); 6 | rep(i, n) dp[i + 1] = dp[i] * (t - i); 7 | per(i, n + 1, 1) pd[i - 1] = pd[i] * (t - i); 8 | rep(i, n + 1) { 9 | T tmp = y[i] * dp[i] * pd[i] * ifact[i] * ifact[n - i]; 10 | ret -= ((n - i) & 1 ? tmp : -tmp); 11 | } 12 | return ret; 13 | } -------------------------------------------------------------------------------- /src/math/matrix.hpp: -------------------------------------------------------------------------------- 1 | 2 | template struct M { 3 | vector> a; 4 | int n, m; 5 | M(int n, int m) : n(n), m(m), a(n, vector(m)) {} 6 | M(int n = 0) : M(n, n) {} 7 | vector& operator[](int k) { return a[k]; } 8 | const vector& operator[](int k) const { return a[k]; } 9 | static M I(int n) { 10 | M mat(n); 11 | rep(i, n) mat[i][i] = 1; 12 | return mat; 13 | } 14 | M& operator+=(const M& b) { 15 | rep(i, n) rep(j, m)(*this)[i][j] += b[i][j]; 16 | return *this; 17 | } 18 | M& operator-=(const M& b) { 19 | rep(i, n) rep(j, m)(*this)[i][j] -= b[i][j]; 20 | return *this; 21 | } 22 | M& operator*=(const M& b) { 23 | int l = b.m; 24 | vector c(n, vector(l)); 25 | rep(i, n) rep(j, m) rep(k, l) c[i][k] += (*this)[i][j] * b[j][k]; 26 | a.swap(c); 27 | return *this; 28 | } 29 | M& operator^=(ll k) { 30 | M b = M::I(n); 31 | while(k) { 32 | if(k & 1) b *= *this; 33 | *this *= *this; 34 | k >>= 1; 35 | } 36 | a.swap(b.a); 37 | return *this; 38 | } 39 | M operator+(const M& b) const { return (M(*this) += b); } 40 | M operator-(const M& b) const { return (M(*this) -= b); } 41 | M operator*(const M& b) const { return (M(*this) *= b); } 42 | M operator^(const M& b) const { return (M(*this) ^= b); } 43 | }; 44 | template pair GaussElimination(M& a, bool LE = false) { 45 | int n = a.n, m = a.m; 46 | int rank = 0, je = LE ? m - 1 : m; 47 | mint det = 1; 48 | rep(j, je) { 49 | int idx = -1; 50 | rep(i, rank, n) { 51 | if(a[i][j].x) { 52 | idx = i; 53 | break; 54 | } 55 | } 56 | if(idx == -1) { 57 | det = 0; 58 | continue; 59 | } 60 | if(rank != idx) { 61 | det = -det; 62 | swap(a[rank], a[idx]); 63 | } 64 | det *= a[rank][j]; 65 | if(LE && a[rank][j].x != 1) { 66 | mint coeff = a[rank][j].inv(); 67 | rep(k, j, m) a[rank][k] *= coeff; 68 | } 69 | int is = LE ? 0 : rank + 1; 70 | rep(i, is, n) { 71 | if(i == rank) continue; 72 | if(a[i][j].x) { 73 | mint coeff = a[i][j] / a[rank][j]; 74 | rep(k, j, m) a[i][k] -= a[rank][k] * coeff; 75 | } 76 | } 77 | rank++; 78 | } 79 | return make_pair(rank, det); 80 | } 81 | 82 | template vector> LinearEquation(M a, vector b) { 83 | int n = a.n, m = a.m; 84 | rep(i, n) a[i].eb(b[i]); 85 | a.m++; 86 | auto p = GaussElimination(a, true); 87 | int rank = p.first; 88 | rep(i, rank, n) { 89 | if(a[i][m].x != 0) return {}; 90 | } 91 | vector> res(1, vector(m)); 92 | vi piv(m, -1); 93 | int j = 0; 94 | rep(i, rank) { 95 | while(a[i][j].x == 0) ++j; 96 | res[0][j] = a[i][m], piv[j] = i; 97 | } 98 | rep(j, m) { 99 | if(piv[j] == -1) { 100 | vector x(m); 101 | x[j] = 1; 102 | rep(k, j) { 103 | if(piv[k] != -1) x[k] = -a[piv[k]][j]; 104 | } 105 | res.eb(x); 106 | } 107 | } 108 | return res; 109 | } -------------------------------------------------------------------------------- /src/math/prime.hpp: -------------------------------------------------------------------------------- 1 | template T pow_mod(T x, U n, T md) { 2 | T r = 1 % md; 3 | x %= md; 4 | while(n) { 5 | if(n & 1) r = (r * x) % md; 6 | x = (x * x) % md; 7 | n >>= 1; 8 | } 9 | return r; 10 | } 11 | bool is_prime(ll n) { 12 | if(n <= 1) return false; 13 | if(n == 2) return true; 14 | if(n % 2 == 0) return false; 15 | ll d = n - 1; 16 | while(d % 2 == 0) d /= 2; 17 | for(ll a : {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}) { 18 | if(n <= a) break; 19 | ll t = d; 20 | ll y = pow_mod(a, t, n); // over 21 | while(t != n - 1 && y != 1 && y != n - 1) { 22 | y = i128(y) * y % n; // flow 23 | t <<= 1; 24 | } 25 | if(y != n - 1 && t % 2 == 0) { return false; } 26 | } 27 | return true; 28 | } 29 | ll pollard_single(ll n) { 30 | ll R; 31 | auto f = [&](ll x) { return (i128(x) * x + R) % n; }; 32 | if(is_prime(n)) return n; 33 | if(n % 2 == 0) return 2; 34 | ll st = 0; 35 | while(true) { 36 | R = rnd(1, n); 37 | st++; 38 | ll x = st, y = f(x); 39 | while(true) { 40 | ll p = gcd((y - x + n), n); 41 | if(p == 0 || p == n) break; 42 | if(p != 1) return p; 43 | x = f(x); 44 | y = f(f(y)); 45 | } 46 | } 47 | } 48 | vl factor(ll n) { 49 | if(n == 1) return {}; 50 | ll x = pollard_single(n); 51 | if(x == n) return {x}; 52 | vl l = factor(x), r = factor(n / x); 53 | return l.insert(end(l), all(r)), l; 54 | } -------------------------------------------------------------------------------- /src/math/primitive-root.hpp: -------------------------------------------------------------------------------- 1 | ll primitive_root(ll p) { 2 | auto v = factor(p - 1); 3 | sort(all(v)), v.erase(unique(all(v)), end(v)); 4 | while(true) { 5 | ll g = rnd(1, p); 6 | bool ok = true; 7 | for(auto d : v) { 8 | ll f = (p - 1) / d; 9 | if(pow_mod(g, f, p) == 1) { 10 | ok = false; 11 | break; 12 | } 13 | } 14 | if(ok) return g; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/math/xor-convolution.hpp: -------------------------------------------------------------------------------- 1 | template void fwt(vector& f, bool inv = false) { 2 | int n = si(f), m = __lg(n); 3 | rep(i, m) { 4 | rep(b, n) { 5 | if(~b >> i & 1) { 6 | T x = f[b], y = f[b ^ 1 << i]; 7 | f[b] = x + y, f[b ^ 1 << i] = x - y; 8 | } 9 | } 10 | } 11 | if(inv) { 12 | T iz = T(1) / T(si(f)); 13 | fore(e, f) e *= iz; 14 | } 15 | } -------------------------------------------------------------------------------- /src/memo/Primes.md: -------------------------------------------------------------------------------- 1 | #### 素数の個数 2 | 3 | | $n$ | $10^2$ | $10^3$ | $10^4$ | $10^5$ | $10^6$ | $10^7$ | $10^8$ | $10^9$ | $10^{10}$ | 4 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | 5 | | $\pi(n)$ | 25 | 168 | 1229 | 9592 | 78498 | 664579 | 5.76e+6 | 5.08e+7 | 4.55e+8 | 6 | 7 | #### 高度合成数 8 | 9 | | $≤n$ | $10^3$ | $10^4$ | $10^5$ | $10^6$ | $10^7$ | $10^8$ | $10^9$ | 10 | | --- | --- | --- | --- | --- | --- | --- | --- | 11 | | $x$ | 840 | 7560 | 83160 | 720720 | 8648640 | 73513440 | 735134400 | 12 | | $d^0(x)$ | 32 | 64 | 128 | 240 | 448 | 768 | 1344 | 13 | 14 | | $≤n$ | $10^{10}$ | $10^{11}$ | $10^{12}$ | $10^{13}$ | $10^{14}$ | $10^{15}$ | $10^{16}$ | $10^{17}$ | $10^{18}$ | 15 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | 16 | | $d^0(x)$ | 2304 | 4032 | 6720 | 10752 | 17280 | 26880 | 41472 | 64512 | 103680 | 17 | 18 | #### 素数階乗 19 | 20 | | $n$ | $2$ | $3$ | $5$ | $7$ | $11$ | $13$ | $17$ | $19$ | $23$ | $29$ | 21 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | 22 | | $n\\#$ | 2 | 6 | 30 | 210 | 2310 | 30030 | 510510 | 9.70e+6 | 2.23e+8 | 6.47e+9 | 23 | 24 | #### 階乗 25 | 26 | | $4!$ | $5!$ | $6!$ | $7!$ | $8!$ | $9!$ | $10!$ | $11!$ | $12!$ | $13!$ | 27 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | 28 | | 24 | 120 | 720 | 5040 | 40320 | 362880 | 3.63e+6 | 3.99e+7 | 4.79e+8 | 6.23e+9 | 29 | -------------------------------------------------------------------------------- /src/memo/math.md: -------------------------------------------------------------------------------- 1 | 2 | ## 二項係数 3 | |n\k|0|1|2|3|4|5|6|7|8|9|10| 4 | |:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------| 5 | |**0**|1| 6 | |**1**|1|1| 7 | |**2**|1|2|1| 8 | |**3**|1|3|3|1| 9 | |**4**|1|4|6|4|1| 10 | |**5**|1|5|10|10|5|1| 11 | |**6**|1|6|15|20|15|6|1| 12 | |**7**|1|7|21|35|35|21|7|1| 13 | |**8**|1|8|28|56|70|56|28|8|1| 14 | |**9**|1|9|36|84|126|126|84|36|9|1| 15 | |**10**|1|10|45|120|210|252|210|120|45|10|1| 16 | |**11**|1|11|55|165|330|462|462|330|165|55|11| 17 | |**12**|1|12|66|220|495|792|924|792|495|220|66| 18 | |**13**|1|13|78|286|715|1287|1a716|1716|1287|715|286| 19 | |**14**|1|14|91|364|1001|2002|3003|3432|3003|2002|1001| 20 | |**15**|1|15|105|455|1365|3003|5005|6435|6435|5005|3003| 21 | |**16**|1|16|120|560|1820|4368|8008|11440|12870|11440|8008| 22 | |**17**|1|17|136|680|2380|6188|12376|19448|24310|24310|19448| 23 | |**18**|1|18|153|816|3060|8568|18564|31824|43758|48620|43758| 24 | |**19**|1|19|171|969|3876|11628|27132|50388|75582|92378|92378| 25 | |**20**|1|20|190|1140|4845|15504|38760|77520|125970|167960|184756| 26 | 27 | $\binom{n}{k}=\binom{n-1}{k-1}+\binom{n-1}{k}$ 28 | $\binom{n}{k}=\frac{n}{k}\binom{n-1}{k-1}$ 29 | $\binom{L}{k}+\dots+\binom{R-1}{k}=\binom{R}{k+1}-\binom{L}{k+1}$ 30 | 31 | ## 第一種スターリング数 32 | $c(n,k)$: $1,2,\dots,n$ の順列で巡回置換 $k$ 個に分割できるものの個数 33 | 34 | |$n$ \ $k$|0|1|2|3|4|5|6|7| 35 | |:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------| 36 | |**0**|1| 37 | |**1**|0|1| 38 | |**2**|0|1|1| 39 | |**3**|0|2|3|1| 40 | |**4**|0|6|11|6|1| 41 | |**5**|0|24|50|35|10|1| 42 | |**6**|0|120|274|225|85|15|1 43 | |**7**|0|720|1764|1624|735|175|21|1 44 | 45 | $c(n,k)=c(n-1,k-1)+(n-1)c(n-1,k)$ 46 | $x(x+1)\dots(x+n-1)=\sum_{k=0}^n c(n,k)x^k$ 47 | $\sum_{k=0}^nc(n,k)=n!$ 48 | $\sum_{k=0}^n 2^kc(n,k)=(n+1)!$ 49 | $\sum_{k=0}^n(-1)^kc(n,k)=0$ 50 | 51 | $\sum_{k=0}^n c(n,k)x^k=x(x+1)\dots(x+n-1)$ を用いて分割統治し,片方の計算を polynomial taylor shift で再利用すると,$c(N,k)$ の $k$ に関する列挙が $O(N\log N)$ 時間でできる. 52 | 53 | ## 第二種スターリング数 54 | $S(n,k)$: $1,2,\dots,n$ を $k$ 個の区別しない集合に分割する方法の数 55 | |$n$ \ $k$|0|1|2|3|4|5|6|7| 56 | |:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------| 57 | |**0**|1| 58 | |**1**|0|1| 59 | |**2**|0|1|1| 60 | |**3**|0|1|3|1| 61 | |**4**|0|1|7|6|1| 62 | |**5**|0|1|15|25|10|1| 63 | |**6**|0|1|31|90|65|15|1 64 | |**7**|0|1|63|301|350|140|21|1 65 | 66 | $S(n,k)=S(n-1,k-1)+kS(n-1,k)$ 67 | $x^n=\sum_{k=0}^nS(n,k)x(x-1)\dots(x-k+1)$ 68 | $S(n,k)=\frac{1}{k!}\sum_{m=1}^k(-1)^{k-m}\binom{k}{m}m^n$ 69 | 70 | 最後の式と畳み込みを使うと $S(N,k)$ の $k$ に関する列挙が $O(N\log N)$ 時間でできる. 71 | 72 | ## ベル数 73 | $B_n$: $1,2,\dots,n$ をいくつかの集合に分割する方法の数 74 | |$n$|0|1|2|3|4|5|6|7|8|9|10| 75 | |:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------| 76 | |$B_n$|1|1|2|5|15|52|203|877|4140|21147|115975| 77 | 78 | $B_{n+1}=\sum_{k=0}^n\binom{n}{k}B_k$ 79 | $B_n=\frac{1}{e}\sum_{k=0}^\infty\frac{k^n}{k!}$ 80 | 81 | 82 | 指数型母関数 $\exp(\exp x - 1)=\sum_{n=0}^\infty B_n\frac{x^n}{n!}$ を使うと $B_0, B_1, \dots, B_n$ の計算が $O(N\log N)$ でできる. 83 | 84 | 85 | ## カタラン数 86 | $C_n$: $n$ 個の $($ と $)$ を括弧列になるように並べる方法の数 87 | |$n$|0|1|2|3|4|5|6|7|8|9|10| 88 | |:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------| 89 | |$C_n$|1|1|2|5|14|42|132|429|1430|4862|16796| 90 | 91 | $C_n=\frac{1}{n+1}\binom{2n}{n}=\frac{(2n)!}{(n+1)!n!}$ 92 | $C_{n+1}=\frac{2(2n+1)}{n+2}C_n$ 93 | $C_{n+1}=\sum_{k=0}^nC_kC_{n-k}$ 94 | 95 | ## モンモール数 96 | $a_n$: $1,2,\dots,n$ の順列 $P$ で $P_i \neq i$ となるものの個数 97 | |$n$|0|1|2|3|4|5|6|7|8|9|10| 98 | |:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------| 99 | |$a_n$||0|1|2|9|44|265|1854|14833|133496|1334961| 100 | 101 | $a_n=(n-1)(a_{n-1}+a_{n-2})$ 102 | $a_n=na_{n-1}+(-1)^n$ 103 | 104 | ## 分割数 105 | $P_n$: $n$ を正の整数の和として表す方法の数 106 | |$n$|0|1|2|3|4|5|6|7|8|9|10| 107 | |:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------| 108 | |$P_n$|1|1|2|3|5|7|11|15|22|30|42| 109 | 110 | 母関数は $\prod_{n=1}^\infty \frac{1}{1-x^n}=\sum_{n=0}^\infty P_nx^n$ である.五角数定理より $\prod_{n=1}^\infty (1-x^n)=\sum_{n=-\infty}^\infty (-1)^nx^{n(3n+1)/2}$ なので,$P_0,P_1,\dots,P_N$ を $O(N\log N)$ 時間で列挙できる. 111 | 112 | ## 母関数 113 | $\frac{1}{1-x}=1+x+x^2+x^3+x^4+\dots=\sum_{n=0}^\infty x^n$ 114 | 115 | $\frac{1}{(1-x)^2}=1+2x+3x^2+4x^3+5x^4+\dots=\sum_{n=0}^\infty (n+1)x^n$ 116 | 117 | $\frac{1}{(1-x)^3}=1+3x+6x^2+10x^3+15x^4+\dots=\sum_{n=0}^\infty \frac{1}{2}(n+1)(n+2)x^n$ 118 | 119 | $\frac{1}{(1-x)^d}=\sum_{n=0}^\infty \binom{n+d-1}{n}x^n$ 120 | 121 | $\sqrt{1-x}=1-\frac{1}{2}x-\frac{1}{8}x^2-\frac{1}{16}x^3-\frac{5}{128}x^4-\dots=1-\sum_{n=1}^\infty \frac{(2n-2)!}{2^{2n-1}n!(n-1)!}x^n$ 122 | 123 | $\frac{1}{\sqrt{1-x}}=1+\frac{1}{2}x+\frac{3}{8}x^2+\frac{5}{16}x^3+\frac{35}{128}x^4-\dots=\sum_{n=0}^\infty \frac{(2n)!}{4^n n!}x^n$ 124 | 125 | $\frac{1-\sqrt{1-4x}} 126 | {2x}=1+x+2x^2+5x^3+14x^4+\dots=\sum_{n=0}^\infty C_nx^n=\sum_{n=0}^\infty \frac{(2n)!}{(n+1)!n!}x^n$ (カタラン数) 127 | 128 | $\frac{1}{\sqrt{1-4x}}=\sum_{n=0}^\infty\binom{2n}{n}x^n$ 129 | 130 | $\frac{1}{1-x-x^2}=1+x+2x^2+3x^3+5x^4+\dots=\sum_{n=0}^\infty F_nx^n$ (フィボナッチ数) 131 | 132 | $\log(1-x)=-x-\frac{1}{2}x^2-\frac{1}{3}x^3-\frac{1}{4}x^4-\dots=\sum_{n=1}^\infty \frac{1}{n}x^n$ 133 | 134 | $\exp(\exp x - 1) = \sum_{n=0}^\infty B_n \frac{x^n}{n}$ (ベル数) 135 | 136 | $\frac{1}{k}(\exp x - 1)^k = \sum_{n=0}^\infty S(n,k)\frac{x^n}{n!}$ (第二種スターリング数) 137 | 138 | $\frac{\exp(-x)}{1-x}=1+\frac{1}{2}x^2+\frac{1}{3}x^3+\frac{3}{8}x^4+\dots=\sum_{n=0}^\infty a_n\frac{x^n}{n!}$ (モンモール数) 139 | 140 | $C(x)^k=\left(\frac{1-\sqrt{1-4x}}{2x}\right)^k=\sum_{n=0}^\infty \frac{k}{n+k}\binom{2n+k-1}{n}$ (カタラン数の母関数の累乗) 141 | 142 | -------------------------------------------------------------------------------- /src/misc/clock.hpp: -------------------------------------------------------------------------------- 1 | struct Timer { 2 | #define C chrono::high_resolution_clock 3 | C::time_point c; 4 | Timer() : c(C::now()) {} 5 | long long elapsed() { 6 | auto d = C::now(); 7 | return chrono::duration_cast(d - c).count(); 8 | } 9 | #undef C 10 | }; -------------------------------------------------------------------------------- /src/misc/simplex.hpp: -------------------------------------------------------------------------------- 1 | template struct Simplex { 2 | const F EPS = F(1.0) / (1LL << DEPS); 3 | int n, m; 4 | vi shuffle_idx; 5 | vi idx; 6 | vector> mat; 7 | int i_ch, j_ch; 8 | 9 | private: 10 | void _initialize(const vector>& A, const vector& b, const vector& c) { 11 | n = c.size(), m = A.size(); 12 | 13 | mat.assign(m + 2, vector(n + 2)); 14 | i_ch = m; 15 | rep(i, m) { 16 | rep(j, n) mat[i][j] = -A[i][j]; 17 | mat[i][n] = 1, mat[i][n + 1] = b[i]; 18 | if(mat[i_ch][n + 1] > mat[i][n + 1]) i_ch = i; 19 | } 20 | rep(j, n) mat[m][j] = c[j]; 21 | mat[m + 1][n] = -1; 22 | 23 | idx.resize(n + m + 1); 24 | iota(idx.begin(), idx.end(), 0); 25 | } 26 | 27 | inline F abs_(F x) noexcept { return x > -x ? x : -x; } 28 | void _solve() { 29 | vi jupd; 30 | for(nb_iter = 0, j_ch = n;; nb_iter++) { 31 | if(i_ch < m) { 32 | swap(idx[j_ch], idx[i_ch + n + 1]); 33 | mat[i_ch][j_ch] = F(1) / mat[i_ch][j_ch]; 34 | jupd.clear(); 35 | rep(j, n + 2) { 36 | if(j != j_ch) { 37 | mat[i_ch][j] *= -mat[i_ch][j_ch]; 38 | if(abs_(mat[i_ch][j]) > EPS) jupd.push_back(j); 39 | } 40 | } 41 | rep(i, m + 2) { 42 | if(abs_(mat[i][j_ch]) < EPS or i == i_ch) continue; 43 | fore(j, jupd) mat[i][j] += mat[i][j_ch] * mat[i_ch][j]; 44 | mat[i][j_ch] *= mat[i_ch][j_ch]; 45 | } 46 | } 47 | 48 | j_ch = -1; 49 | rep(j, n + 1) { 50 | if(j_ch < 0 or idx[j_ch] > idx[j]) { 51 | if(mat[m + 1][j] > EPS or (abs_(mat[m + 1][j]) < EPS and mat[m][j] > EPS)) j_ch = j; 52 | } 53 | } 54 | if(j_ch < 0) break; 55 | 56 | i_ch = -1; 57 | rep(i, m) { 58 | if(mat[i][j_ch] < -EPS) { 59 | if(i_ch < 0) { 60 | i_ch = i; 61 | } else if(mat[i_ch][n + 1] / mat[i_ch][j_ch] - mat[i][n + 1] / mat[i][j_ch] < -EPS) { 62 | i_ch = i; 63 | } else if(mat[i_ch][n + 1] / mat[i_ch][j_ch] - mat[i][n + 1] / mat[i][j_ch] < EPS 64 | and idx[i_ch] > idx[i]) { 65 | i_ch = i; 66 | } 67 | } 68 | } 69 | if(i_ch < 0) { 70 | is_infty = true; 71 | break; 72 | } 73 | } 74 | if(mat[m + 1][n + 1] < -EPS) { 75 | infeasible = true; 76 | return; 77 | } 78 | x.assign(n, 0); 79 | rep(i, m) { 80 | if(idx[n + 1 + i] < n) x[idx[n + 1 + i]] = mat[i][n + 1]; 81 | } 82 | ans = mat[m][n + 1]; 83 | } 84 | 85 | public: 86 | Simplex(vector> A, vector b, vector c) { 87 | is_infty = infeasible = false; 88 | 89 | if(Randomize) { 90 | mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); 91 | 92 | vector, F>> Abs; 93 | rep(i, si(A)) Abs.emplace_back(A[i], b[i]); 94 | shuffle(Abs.begin(), Abs.end(), rng); 95 | A.clear(), b.clear(); 96 | fore(Ab, Abs) A.emplace_back(Ab.first), b.emplace_back(Ab.second); 97 | 98 | shuffle_idx.resize(c.size()); 99 | iota(all(shuffle_idx), 0); 100 | shuffle(all(shuffle_idx), rng); 101 | auto Atmp = A; 102 | auto ctmp = c; 103 | rep(i, si(A)) rep(j, si(A[i])) A[i][j] = Atmp[i][shuffle_idx[j]]; 104 | rep(j, si(c)) c[j] = ctmp[shuffle_idx[j]]; 105 | } 106 | 107 | _initialize(A, b, c); 108 | _solve(); 109 | 110 | if(Randomize and x.size() == c.size()) { 111 | auto xtmp = x; 112 | rep(j, si(c)) x[shuffle_idx[j]] = xtmp[j]; 113 | } 114 | } 115 | unsigned nb_iter; 116 | bool is_infty; 117 | bool infeasible; 118 | vector x; 119 | F ans; 120 | 121 | static void dual(vector>& A, vector& b, vector& c) { 122 | const int n = b.size(), m = c.size(); 123 | vector> At(m, vector(n)); 124 | rep(i, n) rep(j, m) At[j][i] = -A[i][j]; 125 | A = At; 126 | rep(i, n) b[i] = -b[i]; 127 | rep(j, m) c[j] = -c[j]; 128 | b.swap(c); 129 | } 130 | }; -------------------------------------------------------------------------------- /src/modint/BarrettReduction.hpp: -------------------------------------------------------------------------------- 1 | 2 | using U = uint64_t; 3 | struct Barret { 4 | U m, im; 5 | Barret(U mod) : m(mod), im(-1ULL / m + 1) {} 6 | U mul(U a, U b) const { 7 | a *= b; 8 | U x = ((__uint128_t)a * im) >> 64; 9 | a -= x * m; 10 | if((ll)a < 0) a += m; 11 | return a; 12 | } 13 | }; 14 | 15 | constexpr ll mod = 998244353; 16 | static Barret b(mod); 17 | struct mint { 18 | int x; 19 | mint(ll x_ = 0) : x((x_ % mod) + mod) { 20 | if(x >= mod) x -= mod; 21 | } 22 | mint& s(uint xx) { return x = xx < mod ? xx : xx - mod, *this; } 23 | mint operator-() { return mint(-x); } 24 | mint& operator+=(const mint& r) { return s(x + r.x); } 25 | mint& operator-=(const mint& r) { return s(x + mod - r.x); } 26 | mint& operator*=(const mint& r) { return x = b.mul(x, r.x), *this; } 27 | mint& operator/=(const mint& r) { return *this *= r.inv(); } 28 | friend mint operator+(mint l, mint r) { return l += r; } 29 | friend mint operator-(mint l, mint r) { return l -= r; } 30 | friend mint operator*(mint l, mint r) { return l *= r; } 31 | friend mint operator/(mint l, mint r) { return l /= r; } 32 | mint inv() const { return pow(mod - 2); } 33 | mint pow(ll b) const { 34 | mint a = *this, c = 1; 35 | while(b) { 36 | if(b & 1) c *= a; 37 | a *= a; 38 | b >>= 1; 39 | } 40 | return c; 41 | } 42 | }; 43 | using vm = vector; 44 | -------------------------------------------------------------------------------- /src/modint/modint.hpp: -------------------------------------------------------------------------------- 1 | constexpr int mod = 998244353; 2 | struct mint { 3 | int x; 4 | mint(ll x_ = 0) : x(x_ % mod) { 5 | if(x < 0) x += mod; 6 | } 7 | mint operator-() { 8 | auto res = *this; 9 | res.x = (x ? mod - x : 0); 10 | return res; 11 | } 12 | mint& operator+=(mint r) { 13 | if((x += r.x) >= mod) x -= mod; 14 | return *this; 15 | } 16 | mint& operator-=(mint r) { 17 | if((x -= r.x) < 0) x += mod; 18 | return *this; 19 | } 20 | mint& operator*=(mint r) { 21 | x = 1LL * x * r.x % mod; 22 | return *this; 23 | } 24 | mint& operator/=(mint r) { return *this *= r.inv(); } 25 | friend mint operator+(mint a, mint b) { return a += b; } 26 | friend mint operator-(mint a, mint b) { return a -= b; } 27 | friend mint operator*(mint a, mint b) { return a *= b; } 28 | friend mint operator/(mint a, mint b) { return a /= b; } 29 | mint inv() const { return pow(mod - 2); } 30 | mint pow(ll b) const { 31 | mint a = *this, c = 1; 32 | while(b) { 33 | if(b & 1) c *= a; 34 | a *= a; 35 | b >>= 1; 36 | } 37 | return c; 38 | } 39 | }; 40 | using vm = vector; -------------------------------------------------------------------------------- /src/string/KMP.hpp: -------------------------------------------------------------------------------- 1 | // kmp[i] := max{ l ≤ i | s[:l] == s[(i+1)-l:i+1] } 2 | // abacaba -> 0010123 3 | auto KMP(string s) { 4 | vector p(sz(s)); 5 | rep(i, 1, sz(s)) { 6 | ll g = p[i - 1]; 7 | while(g && s[i] != s[g]) g = p[g - 1]; 8 | p[i] = g + (s[i] == s[g]); 9 | } 10 | return p; 11 | } 12 | -------------------------------------------------------------------------------- /src/string/Manacher.hpp: -------------------------------------------------------------------------------- 1 | // 各位置での回文半径を求める 2 | // aaabaaa -> 1214121 3 | // 偶数長の回文を含めて直径を知るには,N+1 個の $ を挿入して 1 を引く 4 | // $a$a$a$b$a$a$a$ -> 123432181234321 5 | auto manacher(string s) { 6 | ll n = sz(s), i = 0, j = 0; 7 | vector r(n); 8 | while(i < n) { 9 | while(i >= j && i + j < n && s[i - j] == s[i + j]) j++; 10 | r[i] = j; 11 | ll k = 1; 12 | while(i >= k && i + k < n && k + r[i - k] < j) { 13 | r[i + k] = r[i - k]; 14 | k++; 15 | } 16 | i += k, j -= k; 17 | } 18 | return r; 19 | } 20 | -------------------------------------------------------------------------------- /src/string/RollingHash.hpp: -------------------------------------------------------------------------------- 1 | const ll mod = (1LL << 61) - 1; 2 | ll add(ll a, ll b) { return (a += b) >= mod ? a - mod : a; } 3 | ll mul(ll a, ll b) { 4 | i128 c = (i128)a * b; 5 | return add(c >> 61, c & mod); 6 | } 7 | ll r = 7954398468495; 8 | struct RH { 9 | ll n; 10 | vl hs, pw; 11 | RH(string s) : n(si(s)), hs(n + 1), pw(n + 1, 1) { 12 | rep(i, n) { 13 | pw[i + 1] = mul(pw[i], r); 14 | hs[i + 1] = add(mul(hs[i], r), s[i]); 15 | } 16 | } 17 | ll get(ll l, ll r) const { return add(hs[r], mod - mul(hs[l], pw[r - l])); } 18 | int lcp(int i, int j) { 19 | int ok = 0, ng = min(n - i, n - j) + 1; 20 | while(ok < ng - 1) { 21 | int mid = ok + ng >> 1; 22 | (get(i, i + mid) == get(j, j + mid) ? ok : ng) = mid; 23 | } 24 | return ok; 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /src/string/SuffixArray.hpp: -------------------------------------------------------------------------------- 1 | // returns pair{sa, lcp} 2 | // sa 長さ n : s[sa[0]:] < s[sa[1]:] < … < s[sa[n-1]:] 3 | // lcp 長さ n-1 : lcp[i] = LCP(s[sa[i]:], s[sa[i+1]:]) 4 | auto SA(string s) { 5 | ll n = si(s) + 1, lim = 256; 6 | // assert(lim > ranges::max(s)); 7 | vector sa(n), lcp(n), x(all(s) + 1), y(n), ws(max(n, lim)), rk(n); 8 | iota(all(sa), 0); 9 | for(ll j = 0, p = 0; p < n; j = max(1LL, j * 2), lim = p) { 10 | p = j; 11 | iota(all(y), n - j); 12 | rep(i, 0, n) if(sa[i] >= j) y[p++] = sa[i] - j; 13 | fill(all(ws), 0); 14 | rep(i, 0, n) ws[x[i]]++; 15 | rep(i, 1, lim) ws[i] += ws[i - 1]; 16 | for(ll i = n; i--;) sa[--ws[x[y[i]]]] = y[i]; 17 | swap(x, y); 18 | p = 1; 19 | x[sa[0]] = 0; 20 | rep(i, 1, n) { 21 | ll a = sa[i - 1], b = sa[i]; 22 | x[b] = (y[a] == y[b] && y[a + j] == y[b + j]) ? p - 1 : p++; 23 | } 24 | } 25 | rep(i, 1, n) rk[sa[i]] = i; 26 | for(ll i = 0, k = 0; i < n - 1; lcp[rk[i++]] = k) { 27 | if(k) k--; 28 | while(s[i + k] == s[sa[rk[i] - 1] + k]) k++; 29 | } 30 | sa.erase(begin(sa)); 31 | lcp.erase(begin(lcp)); 32 | return pair{sa, lcp}; 33 | } 34 | -------------------------------------------------------------------------------- /src/string/Zalgorithm.hpp: -------------------------------------------------------------------------------- 1 | template vi z_algorithm(const vector& s) { 2 | int n = si(s), l = -1, r = -1; 3 | vi z(n, n); 4 | rep(i, 1, n) { 5 | int& x = z[i] = i < r ? min(r - i, z[i - l]) : 0; 6 | while(i + x < n and s[i + x] == s[x]) x++; 7 | if(i + x > r) l = i, r = i + x; 8 | } 9 | return z; 10 | } -------------------------------------------------------------------------------- /src/string/enumerate-runs.hpp: -------------------------------------------------------------------------------- 1 | 2 | // (length, l, r) 3 | template vector> enum_runs(const vector& s) { 4 | int n = si(s); 5 | vector> res; 6 | auto dfs = [&](auto&& f, int l, int r) -> void { 7 | if(r - l <= 1) return; 8 | int m = l + r >> 1; 9 | f(f, l, m), f(f, m, r); 10 | vector sl(s.rbegin() + n - m, s.rbegin() + n - l); 11 | sl.insert(sl.end(), s.rbegin() + n - r, s.rbegin() + n - l); 12 | vector sr(s.begin() + m, s.begin() + r); 13 | sr.insert(sr.end(), s.begin() + l, s.begin() + r); 14 | auto zsl = z_algorithm(sl), zsr = z_algorithm(sr); 15 | rep(t, 1, m - l + 1) { 16 | int ml = max(l, m - t - zsl[t]), mr = min(r, m + zsr[r - l - t]); 17 | if(mr - ml >= 2 * t and (ml == 0 or s[ml - 1] != s[ml + t - 1]) and (mr == n or s[mr] != s[mr - t])) 18 | res.push_back({ml, mr, t}); 19 | } 20 | for(int t = 1; t <= r - m; t++) { 21 | int ml = max(l, m - zsl[r - l - t]), mr = min(r, m + t + zsr[t]); 22 | if(mr - ml >= 2 * t and (ml == 0 or s[ml - 1] != s[ml + t - 1]) and (mr == n or s[mr] != s[mr - t])) 23 | res.push_back({ml, mr, t}); 24 | } 25 | }; 26 | dfs(dfs, 0, n); 27 | sort(all(res)); 28 | vector> nres; 29 | int pl = -1, pr = -1; 30 | for(auto [l, r, t] : res) { 31 | if(l == pl and r == pr) continue; 32 | pl = l, pr = r; 33 | nres.push_back({t, l, r}); 34 | } 35 | return nres; 36 | } 37 | -------------------------------------------------------------------------------- /src/template/0settings.sh: -------------------------------------------------------------------------------- 1 | export CXXFLAGS='-O3 -std=c++2a -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC -Wfatal-errors' -------------------------------------------------------------------------------- /src/template/1template.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | using namespace std; 4 | #define ll long long 5 | #define pii pair 6 | #define pll pair 7 | #define vi vector 8 | #define vl vector 9 | #define ov4(a, b, c, d, name, ...) name 10 | #define rep3(i, a, b, c) for(ll i = (a); i < (b); i += (c)) 11 | #define rep2(i, a, b) rep3(i, a, b, 1) 12 | #define rep1(i, n) rep2(i, 0, n) 13 | #define rep0(n) rep1(aaaaa, n) 14 | #define rep(...) ov4(__VA_ARGS__, rep3, rep2, rep1, rep0)(__VA_ARGS__) 15 | #define per(i, a, b) for(ll i = (a)-1; i >= (b); i--) 16 | #define fore(e, v) for(auto&& e : v) 17 | #define all(a) begin(a), end(a) 18 | #define si(a) (int)(size(a)) 19 | #define lb(v, x) (lower_bound(all(v), x) - begin(v)) 20 | #define eb emplace_back 21 | 22 | template bool chmin(T& a, const S& b) { return a > b ? a = b, 1 : 0; } 23 | template bool chmax(T& a, const S& b) { return a < b ? a = b, 1 : 0; } 24 | 25 | const int INF = 1e9 + 100; 26 | const ll INFL = 3e18 + 100; 27 | 28 | #define i128 __int128_t 29 | 30 | struct _ { 31 | _() { cin.tie(0)->sync_with_stdio(0), cout.tie(0); } 32 | } __; -------------------------------------------------------------------------------- /src/template/hash.sh: -------------------------------------------------------------------------------- 1 | # 使い方: sh hash.sh -> コピペ -> Ctrl + D 2 | # コメント・空白・改行を削除して md5 でハッシュする 3 | g++ -dD -E -P -fpreprocessed - | tr -d '[:space:]' | md5sum | cut -c-6 4 | -------------------------------------------------------------------------------- /src/template/random_test.sh: -------------------------------------------------------------------------------- 1 | # correct wrong generate 2 | make $1 3 | make $2 4 | make $3 5 | while true;do 6 | ./$3 > input.txt 7 | c=$(./$1 < input.txt) 8 | w=$(./$2 < input.txt) 9 | if [[ $c = $w ]]; then 10 | echo "pass" 11 | else 12 | echo "WA" 13 | echo "$(cat input.txt)" 14 | echo "o:" 15 | echo "$c" 16 | echo "x:" 17 | echo "$w" 18 | exit 19 | fi 20 | done -------------------------------------------------------------------------------- /src/template/rnd.hpp: -------------------------------------------------------------------------------- 1 | ll rnd(ll l, ll r) { //[l, r) 2 | static mt19937_64 gen(chrono::steady_clock::now().time_since_epoch().count()); 3 | return uniform_int_distribution(l, r - 1)(gen); 4 | } 5 | template void rndshuf(vector& v) { rep(i, 1, si(v)) swap(v[i], v[rnd(0, i)]); } 6 | template vector rvi(int n, T l, T r, bool unique = false) { 7 | if(unique) { 8 | assert(r - l >= n); 9 | vector res; 10 | rep(i, n) res.eb(rnd(l, r - n + 1)); 11 | sort(all(res)); 12 | rep(i, n) res[i] += i; 13 | rndshuf(res); 14 | return res; 15 | } 16 | vector v(n); 17 | fore(e, v) e = rnd(l, r); 18 | return v; 19 | } -------------------------------------------------------------------------------- /src/tree/block-cut-tree.hpp: -------------------------------------------------------------------------------- 1 | struct extended_block_cut_tree { 2 | int N, cnt; 3 | vector> G; 4 | extended_block_cut_tree(vector>& E) { 5 | N = E.size(); 6 | vector next(N, -1); 7 | vector d(N, -1); 8 | vector imos(N, 0); 9 | for(int i = 0; i < N; i++) { 10 | if(d[i] == -1) { 11 | d[i] = 0; 12 | dfs1(E, next, d, imos, i); 13 | } 14 | } 15 | cnt = 0; 16 | G.resize(N + 1); 17 | vector used(N, false); 18 | for(int i = 0; i < N; i++) { 19 | if(d[i] == 0) { dfs2(E, d, imos, used, cnt, i); } 20 | if(E[i].empty()) { 21 | G[i].push_back(N + cnt); 22 | G[N + cnt].push_back(i); 23 | cnt++; 24 | G.push_back({}); 25 | } 26 | } 27 | G.pop_back(); 28 | } 29 | void dfs1(vector>& E, vector& next, vector& d, vector& imos, int v) { 30 | for(int w : E[v]) { 31 | if(d[w] == -1) { 32 | d[w] = d[v] + 1; 33 | next[v] = w; 34 | dfs1(E, next, d, imos, w); 35 | imos[v] += imos[w]; 36 | } else if(d[w] < d[v] - 1) { 37 | imos[v]++; 38 | imos[next[w]]--; 39 | } 40 | } 41 | } 42 | void dfs2(vector>& E, vector& d, vector& imos, vector& used, int b, int v) { 43 | used[v] = true; 44 | bool ok = false; 45 | for(int w : E[v]) { 46 | if(d[w] == d[v] + 1 && !used[w]) { 47 | if(imos[w] > 0) { 48 | if(!ok) { 49 | ok = true; 50 | G[v].push_back(N + b); 51 | G[N + b].push_back(v); 52 | } 53 | dfs2(E, d, imos, used, b, w); 54 | } else { 55 | G[v].push_back(N + cnt); 56 | G[N + cnt].push_back(v); 57 | cnt++; 58 | G.push_back({}); 59 | dfs2(E, d, imos, used, cnt - 1, w); 60 | } 61 | } 62 | } 63 | if(!ok && d[v] > 0) { 64 | G[v].push_back(N + b); 65 | G[N + b].push_back(v); 66 | } 67 | } 68 | int size() { return G.size(); } 69 | vector& operator[](int v) { return G[v]; } 70 | }; -------------------------------------------------------------------------------- /src/tree/hld.hpp: -------------------------------------------------------------------------------- 1 | template struct HLD { 2 | int n; 3 | G& g; 4 | vector sub, in, out, head, rev, par, d; 5 | HLD(G& g) : n(si(g)), g(g), sub(n), in(n), out(n), head(n), rev(n), par(n), d(n) {} 6 | void dfs1(int x, int p) { 7 | par[x] = p; 8 | sub[x] = 1; 9 | if(g[x].size() and g[x][0] == p) swap(g[x][0], g[x].back()); 10 | fore(e, g[x]) { 11 | if(e == p) continue; 12 | d[e] = d[x] + 1; 13 | dfs1(e, x); 14 | sub[x] += sub[e]; 15 | if(sub[g[x][0]] < sub[e]) swap(g[x][0], e); 16 | } 17 | } 18 | void dfs2(int x, int p, int& t) { 19 | in[x] = t++; 20 | rev[in[x]] = x; 21 | fore(e, g[x]) { 22 | if(e == p) continue; 23 | head[e] = (g[x][0] == e ? head[x] : e); 24 | dfs2(e, x, t); 25 | } 26 | out[x] = t; 27 | } 28 | void build() { 29 | int t = 0; 30 | head[0] = 0; 31 | dfs1(0, -1); 32 | dfs2(0, -1, t); 33 | } 34 | int la(int v, int k) { 35 | while(1) { 36 | int u = head[v]; 37 | if(in[v] - k >= in[u]) return rev[in[v] - k]; 38 | k -= in[v] - in[u] + 1; 39 | v = par[u]; 40 | } 41 | } 42 | int lca(int u, int v) { 43 | for(;; v = par[head[v]]) { 44 | if(in[u] > in[v]) swap(u, v); 45 | if(head[u] == head[v]) return u; 46 | } 47 | } 48 | template 49 | T query(int u, int v, const T& e, const Q& q, const F& f, bool edge = false) { 50 | T l = e, r = e; 51 | for(;; v = par[head[v]]) { 52 | if(in[u] > in[v]) swap(u, v), swap(l, r); 53 | if(head[u] == head[v]) break; 54 | l = f(q(in[head[v]], in[v] + 1), l); 55 | } 56 | return f(f(q(in[u] + edge, in[v] + 1), l), r); 57 | } 58 | int dist(int u, int v) { return d[u] + d[v] - 2 * d[lca(u, v)]; } 59 | int jump(int s, int t, int i) { 60 | if(!i) return s; 61 | int l = lca(s, t); 62 | int dst = d[s] + d[t] - d[l] * 2; 63 | if(dst < i) return -1; 64 | if(d[s] - d[l] >= i) return la(s, i); 65 | i -= d[s] - d[l]; 66 | return la(t, d[t] - d[l] - i); 67 | } 68 | }; -------------------------------------------------------------------------------- /test/FPS/FFT.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/convolution_mod" 2 | #include "test/template.hpp" 3 | #include "src/modint/modint.hpp" 4 | #include "src/FPS/FFT.hpp" 5 | 6 | int main() { 7 | cin.tie(0)->sync_with_stdio(0); 8 | ll N, M; 9 | cin >> N >> M; 10 | vector A(N), B(M); 11 | for(mm& a : A) cin >> a.x; 12 | for(mm& b : B) cin >> b.x; 13 | 14 | auto C = conv(move(A), move(B)); 15 | rep(i, 0, sz(C)) cout << C[i].x << " \n"[i + 1 == sz(C)]; 16 | } 17 | -------------------------------------------------------------------------------- /test/FPS/FFT_fast.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/convolution_mod" 2 | #include "test/template.hpp" 3 | #include "src/extra/modint_fast.hpp" 4 | #include "src/FPS/FFT_fast.hpp" 5 | 6 | int main() { 7 | cin.tie(0)->sync_with_stdio(0); 8 | ll N, M; 9 | cin >> N >> M; 10 | vector A(N), B(M); 11 | for(mm& a : A) cin >> a.x; 12 | for(mm& b : B) cin >> b.x; 13 | 14 | auto C = conv(move(A), move(B)); 15 | rep(i, 0, sz(C)) cout << C[i].x << " \n"[i + 1 == sz(C)]; 16 | } 17 | -------------------------------------------------------------------------------- /test/benchmark/FFT.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | namespace nyaan { 6 | 7 | // ここにライブラリを貼る 8 | 9 | } // namespace nyaan 10 | // #include "atcoder/convolution" 11 | 12 | #include "test/template.hpp" 13 | 14 | namespace fft1 { 15 | #include "src/modint/modint.hpp" 16 | #include "src/FPS/FFT.hpp" 17 | } // namespace fft1 18 | namespace fft2 { 19 | #include "src/extra/modint_fast.hpp" 20 | #include "src/FPS/FFT_fast.hpp" 21 | } // namespace fft2 22 | 23 | int main() { 24 | using namespace chrono; 25 | const ll N = 1 << 20; 26 | { 27 | vector A(N), B(N); 28 | rep(i, 0, N) A[i] = B[i] = i; 29 | auto s = system_clock::now(); 30 | auto C = fft1::conv(A, B); 31 | cout << "my FFT: " << duration_cast(system_clock::now() - s).count() << " ms" << endl; 32 | } 33 | { 34 | vector A(N), B(N); 35 | rep(i, 0, N) A[i] = B[i] = i; 36 | auto s = system_clock::now(); 37 | auto C = fft2::conv(A, B); 38 | cout << "my fast FFT: " << duration_cast(system_clock::now() - s).count() << " ms" << endl; 39 | } 40 | { 41 | vector A(N), B(N); 42 | rep(i, 0, N) A[i] = B[i] = i; 43 | auto s = system_clock::now(); 44 | auto C = atcoder::convolution(A, B); 45 | cout << "ACL: " << duration_cast(system_clock::now() - s).count() << " ms" << endl; 46 | } 47 | { 48 | const int MOD = 998244353; 49 | using mint = nyaan::LazyMontgomeryModInt; 50 | nyaan::NTT ntt; 51 | vector A(N), B(N); 52 | rep(i, 0, N) A[i] = B[i] = i; 53 | auto s = system_clock::now(); 54 | auto C = ntt.multiply(A, B); 55 | cout << "nyaan AVX2: " << duration_cast(system_clock::now() - s).count() << " ms" << endl; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /test/benchmark/FastSet.cpp: -------------------------------------------------------------------------------- 1 | #include "test/template.hpp" 2 | using u64 = uint64_t; 3 | #include "src/data-structure/FastSet.hpp" 4 | 5 | mt19937 rnd; 6 | int main() { 7 | auto test = [&](const vector& query, const string& name, auto add, auto next) { 8 | using namespace chrono; 9 | ll ans = 0; 10 | auto s = system_clock::now(); 11 | for(ll x : query) { 12 | add(x); 13 | ans += next(x); 14 | } 15 | cout << name << ": " << duration_cast(system_clock::now() - s).count() << " ms" << endl; 16 | cerr << ans << endl; 17 | }; 18 | 19 | const ll N = 1 << 21; 20 | const ll MAX = 1 << 30; 21 | cout << "N = " << N << ", MAX = " << MAX << endl; 22 | vector query(N); 23 | rep(i, 0, N) query[i] = rnd() >> 2; 24 | shuffle(all(query), rnd); 25 | { 26 | std::set s; 27 | test( 28 | query, "std::set", [&](ll x) { s.insert(x); }, 29 | [&](ll x) -> ll { 30 | auto p = s.upper_bound(x); 31 | if(p == end(s)) return MAX; 32 | return *p; 33 | }); 34 | } 35 | { 36 | static bitset s; 37 | test( 38 | query, "std::bitset", [&](ll x) { s[x] = 1; }, [&](ll x) { return s._Find_next(x); }); 39 | } 40 | { 41 | FastSet s(MAX); 42 | test( 43 | query, "FastSet", [&](ll x) { s.set(x); }, [&](ll x) { return s.next(x); }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /test/benchmark/SuffixArray.cpp: -------------------------------------------------------------------------------- 1 | #include "test/template.hpp" 2 | #include "src/string/SuffixArray.hpp" 3 | // #include "atcoder/string" 4 | 5 | mt19937 rnd; 6 | int main() { 7 | using namespace chrono; 8 | const ll N = 1 << 20; 9 | string S(N, 0); 10 | rep(i, 0, N) S[i] = rnd() % 26 + 'A'; 11 | { 12 | auto s = system_clock::now(); 13 | auto [sa, lcp] = SA(S); 14 | cout << "my Suffix Array: " << duration_cast(system_clock::now() - s).count() << " ms" << endl; 15 | } 16 | { 17 | auto s = system_clock::now(); 18 | auto sa = atcoder::suffix_array(S); 19 | auto lcp = atcoder::lcp_array(S, sa); 20 | cout << "ACL: " << duration_cast(system_clock::now() - s).count() << " ms" << endl; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/data-structure/BIT.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/point_add_range_sum" 2 | #include "test/template.hpp" 3 | #include "src/data-structure/BIT.hpp" 4 | 5 | int main() { 6 | cin.tie(0)->sync_with_stdio(0); 7 | 8 | ll N, Q; 9 | cin >> N >> Q; 10 | 11 | BIT A(N); 12 | rep(i, 0, N) { 13 | ll a; 14 | cin >> a; 15 | A.add(i, a); 16 | } 17 | 18 | while(Q--) { 19 | ll a, b, c; 20 | cin >> a >> b >> c; 21 | if(a == 0) A.add(b, c); 22 | else cout << A.sum(b, c) << '\n'; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/data-structure/FastSet.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/predecessor_problem" 2 | #include "test/template.hpp" 3 | using u64 = uint64_t; 4 | #include "src/data-structure/FastSet.hpp" 5 | 6 | int main() { 7 | cin.tie(0)->sync_with_stdio(0); 8 | ll N, Q; 9 | cin >> N >> Q; 10 | string S; 11 | cin >> S; 12 | FastSet s(N); 13 | rep(i, 0, N) if(S[i] == '1') s.set(i); 14 | while(Q--) { 15 | ll c, k; 16 | cin >> c >> k; 17 | if(c == 0) s.set(k); 18 | if(c == 1) s.reset(k); 19 | if(c == 2) cout << (s.a[0][k / B] >> (k % B) & 1) << '\n'; 20 | if(c == 3) { 21 | ll ans = s.next(k - 1); 22 | cout << (ans == N ? -1 : ans) << '\n'; 23 | } 24 | if(c == 4) cout << s.prev(k + 1) << '\n'; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/math/BinaryGCD.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A" 2 | #include "test/template.hpp" 3 | using u64 = uint64_t; 4 | #include "src/math/BinaryGCD.hpp" 5 | 6 | int main() { 7 | mt19937_64 rnd; 8 | rep(shift, 0, 64) { 9 | rep(i, 0, (ll)1e5) { 10 | u64 a = rnd() >> shift, b = rnd() >> shift; 11 | assert(gcd(a, b) == binary_gcd(a, b)); 12 | } 13 | } 14 | puts("Hello World"); 15 | } 16 | -------------------------------------------------------------------------------- /test/math/ExtGCD.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A" 2 | #include "test/template.hpp" 3 | #include "src/math/ExtGCD.hpp" 4 | 5 | using i128 = __int128_t; 6 | i128 abs(i128 x) { return x < 0 ? -x : x; } 7 | int main() { 8 | mt19937_64 rnd; 9 | rep(shift, 1, 64) { 10 | rep(i, 0, (ll)5e4) { 11 | ll a = rnd() >> shift; 12 | ll b = rnd() >> shift; 13 | const ll g = gcd(a, b); 14 | ll x, y; 15 | assert(extgcd(a, b, x, y) == g); 16 | assert((i128)a * x + (i128)b * y == g); 17 | if(g) { 18 | assert(abs((i128)x) + abs((i128)y) <= abs((i128)x - b / g) + abs((i128)y + a / g)); 19 | assert(abs((i128)x) + abs((i128)y) <= abs((i128)x + b / g) + abs((i128)y - a / g)); 20 | } 21 | } 22 | } 23 | puts("Hello World"); 24 | } 25 | -------------------------------------------------------------------------------- /test/modint/BarrettReduction.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A" 2 | #include "test/template.hpp" 3 | using u64 = uint64_t; 4 | #include "src/modint/BarrettReduction.hpp" 5 | 6 | mt19937 rnd(random_device{}()); 7 | int main() { 8 | rep(i, 0, 1e5) { 9 | const u64 mod = rnd(), a = rnd(), b = rnd(), ans1 = Barrett(mod).mul(a, b), ans2 = a * b % mod; 10 | if(mod == 0) continue; 11 | assert(ans1 == ans2); 12 | } 13 | puts("Hello World"); 14 | } 15 | -------------------------------------------------------------------------------- /test/modint/modint.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A" 2 | #include "test/template.hpp" 3 | #include "src/modint/modint.hpp" 4 | 5 | mt19937 rnd(random_device{}()); 6 | int main() { 7 | rep(i, 0, 1e5) { 8 | const ll a = rnd() % mod, b = rnd() % mod; 9 | mm A = a, B = b, C = A * B; 10 | assert((A + B).x == (a + b) % mod); 11 | assert((A - B).x == (a - b + mod) % mod); 12 | assert(C.x == (a * b) % mod); 13 | assert((A / B.inv()).x == C.x); 14 | A = a; 15 | assert((A += B).x == (a + b) % mod); 16 | A = a; 17 | assert((A -= B).x == (a - b + mod) % mod); 18 | A = a; 19 | assert((A *= B).x == (a * b) % mod); 20 | A = a; 21 | assert((A /= B.inv()).x == C.x); 22 | } 23 | puts("Hello World"); 24 | } 25 | -------------------------------------------------------------------------------- /test/string/KMP.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_14_B" 2 | #include "test/template.hpp" 3 | #include "src/string/KMP.hpp" 4 | 5 | int main() { 6 | cin.tie(0)->sync_with_stdio(0); 7 | string S, T; 8 | cin >> S >> T; 9 | auto s = T + '$' + S; 10 | auto kmp = KMP(s); 11 | 12 | rep(i, sz(s) - sz(S), sz(s)) { 13 | if(kmp[i] == sz(T)) cout << i - sz(T) * 2 << '\n'; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/string/LCP.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/number_of_substrings" 2 | #include "test/template.hpp" 3 | #include "src/string/SuffixArray.hpp" 4 | 5 | int main() { 6 | cin.tie(0)->sync_with_stdio(0); 7 | string S; 8 | cin >> S; 9 | const ll N = sz(S); 10 | auto [sa, lcp] = SA(S); 11 | cout << N * (N + 1) / 2 - accumulate(all(lcp), 0LL) << endl; 12 | } 13 | -------------------------------------------------------------------------------- /test/string/Manacher.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/enumerate_palindromes" 2 | #include "test/template.hpp" 3 | #include "src/string/Manacher.hpp" 4 | 5 | int main() { 6 | cin.tie(0)->sync_with_stdio(0); 7 | string S; 8 | cin >> S; 9 | const ll N = sz(S); 10 | string T(N * 2 + 1, '$'); 11 | rep(i, 0, N) T[i * 2 + 1] = S[i]; 12 | auto r = manacher(T); 13 | rep(i, 1, N * 2) { 14 | if(i & 1) cout << r[i] - 1 << " \n"[i + 1 == N * 2]; 15 | else cout << r[i] - 1 << ' '; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/string/RollingHash.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/zalgorithm" 2 | #include "test/template.hpp" 3 | using u64 = uint64_t; 4 | #include "src/string/RollingHash.hpp" 5 | 6 | int main() { 7 | cin.tie(0)->sync_with_stdio(0); 8 | string S; 9 | cin >> S; 10 | RH rh(S); 11 | const ll N = sz(S); 12 | auto LCP = [&](ll i, ll j) { 13 | ll ok = 0, ng = N + 1 - j; 14 | while(ng - ok > 1) { 15 | const ll mid = (ok + ng) / 2; 16 | (rh.get(i, i + mid) == rh.get(j, j + mid) ? ok : ng) = mid; 17 | } 18 | return ok; 19 | }; 20 | rep(i, 0, N) cout << LCP(0, i) << " \n"[i + 1 == N]; 21 | } 22 | -------------------------------------------------------------------------------- /test/string/SuffixArray.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/suffixarray" 2 | #include "test/template.hpp" 3 | #include "src/string/SuffixArray.hpp" 4 | 5 | int main() { 6 | cin.tie(0)->sync_with_stdio(0); 7 | string S; 8 | cin >> S; 9 | const ll N = sz(S); 10 | auto [sa, lcp] = SA(S); 11 | rep(i, 0, N) cout << sa[i] << " \n"[i + 1 == N]; 12 | } 13 | -------------------------------------------------------------------------------- /test/string/Zalgorithm.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/zalgorithm" 2 | #include "test/template.hpp" 3 | #include "src/string/Zalgorithm.hpp" 4 | 5 | int main() { 6 | cin.tie(0)->sync_with_stdio(0); 7 | string S; 8 | cin >> S; 9 | auto z = Z(S); 10 | rep(i, 0, sz(S)) cout << z[i] << " \n"[i + 1 == sz(S)]; 11 | } 12 | -------------------------------------------------------------------------------- /test/template.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | using ll = long long; 4 | const ll INF = LLONG_MAX / 4; 5 | #define rep(i, a, b) for(ll i = a; i < (b); i++) 6 | #define all(a) begin(a), end(a) 7 | #define sz(a) ssize(a) 8 | bool chmin(auto& a, auto b) { return a > b ? a = b, 1 : 0; } 9 | bool chmax(auto& a, auto b) { return a < b ? a = b, 1 : 0; } 10 | -------------------------------------------------------------------------------- /test/template.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A" 2 | #include "test/template.hpp" 3 | 4 | int main() { 5 | ll a = 0; 6 | assert(chmin(a, 1) == 0); 7 | assert(chmax(a, 1) == 1); 8 | assert(chmax(a, 1) == 0); 9 | assert(chmin(a, 0) == 1); 10 | puts("Hello World"); 11 | } 12 | --------------------------------------------------------------------------------