From 2884eaf4b7099b96ac6d79724d1453d27a453e1c Mon Sep 17 00:00:00 2001 From: WIDA <140591203+hh2048@users.noreply.github.com> Date: Wed, 13 Nov 2024 02:18:13 +0800 Subject: [PATCH] =?UTF-8?q?2024.11.13=20=E6=9B=B4=E6=96=B0=EF=BC=9A=20?= =?UTF-8?q?=E8=B0=83=E6=95=B4=EF=BC=9A=E3=80=8A=E5=8F=96=E6=A8=A1=E7=B1=BB?= =?UTF-8?q?=E3=80=8B=E7=A7=BB=E5=8A=A8=E8=87=B3=E3=80=8A=E6=95=B0=E8=AE=BA?= =?UTF-8?q?=E3=80=8B=E7=AB=A0=E8=8A=82=EF=BC=8C=E5=B9=B6=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E5=90=8D=E7=A7=B0=E4=B8=BA=E3=80=8A=E5=8F=96=E6=A8=A1=E8=BF=90?= =?UTF-8?q?=E7=AE=97=E7=B1=BB=E3=80=8B=20=E6=96=B0=E5=A2=9E=EF=BC=9A?= =?UTF-8?q?=E5=BF=AB=E8=AF=BB=E3=80=81=E5=9C=86=E6=96=B9=E6=A0=91=EF=BC=88?= =?UTF-8?q?BlockCutTree=EF=BC=89=E3=80=81=E5=A4=A7=E6=95=B0=E5=BF=AB?= =?UTF-8?q?=E9=80=9F=E5=8F=96=E6=A8=A1=E8=BF=90=E7=AE=97=E7=B1=BB=EF=BC=88?= =?UTF-8?q?Barrett=20&=20DynModInt,=20with=20ModIntBase=EF=BC=89=E3=80=81?= =?UTF-8?q?=E5=BF=AB=E9=80=9F=E5=8F=96=E6=A8=A1=E8=BF=90=E7=AE=97=E7=B1=BB?= =?UTF-8?q?=EF=BC=88MontgomeryModInt32=20=E8=92=99=E5=93=A5=E9=A9=AC?= =?UTF-8?q?=E5=88=A9=E6=A8=A1=E4=B9=98=EF=BC=89=E3=80=81=E5=A4=9A=E9=A1=B9?= =?UTF-8?q?=E5=BC=8F=EF=BC=88Poly,=20with=20MontgomeryModInt32=EF=BC=89=20?= =?UTF-8?q?=E5=B0=8F=E4=BF=AE=E6=94=B9=EF=BC=9A=E5=8A=A8=E6=80=81=E5=8F=96?= =?UTF-8?q?=E6=A8=A1=E7=B1=BB=EF=BC=88ModIntBase=EF=BC=89=E3=80=81?= =?UTF-8?q?=E5=90=8E=E7=BC=80=E6=95=B0=E7=BB=84=EF=BC=88SuffixArray?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../05 - \345\277\253\350\257\273.cpp" | 54 ++ ... \345\234\206\346\226\271\346\240\221.cpp" | 65 ++ ...\347\261\273\357\274\210Z\357\274\211.cpp" | 2 +- ...3\357\274\210MLong & MInt\357\274\211.cpp" | 2 +- ...273\357\274\210ModIntBase\357\274\211.cpp" | 9 +- ...1\346\250\241\344\271\230\357\274\211.cpp" | 206 +++++ ...7\346\250\241\344\271\230\357\274\211.cpp" | 286 ++++++ ...1\344\270\211\350\247\222\357\274\211.cpp" | 0 ...210Comb, with. ModIntBase\357\274\211.cpp" | 0 ...1\345\217\226\346\250\241\357\274\211.cpp" | 2 +- ...7\357\274\210Poly, with Z\357\274\211.cpp" | 2 +- ..., with MontgomeryModInt32\357\274\211.cpp" | 863 ++++++++++++++++++ ...57\274\210Poly, with MInt\357\274\211.cpp" | 2 +- ...iller-Rabin & Pollard-Rho\357\274\211.cpp" | 0 ...272\246\357\274\210BigInt\357\274\211.cpp" | 0 .../11 - Link-Cut Tree.md" | 0 ...04\357\274\210SuffixArray\357\274\211.cpp" | 40 +- ...347\273\204\357\274\210SA\357\274\211.cpp" | 2 +- 18 files changed, 1511 insertions(+), 24 deletions(-) create mode 100644 "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/01 - \346\235\202\347\261\273/05 - \345\277\253\350\257\273.cpp" create mode 100644 "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/02 - \345\233\276\344\270\216\347\275\221\347\273\234/09 - \345\234\206\346\226\271\346\240\221.cpp" rename "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/05A - \345\217\226\346\250\241\347\261\273\357\274\210Z \346\227\247\347\211\210\357\274\211.cpp" => "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07A - \345\217\226\346\250\241\350\277\220\347\256\227\347\261\273\357\274\210Z\357\274\211.cpp" (94%) rename "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/05B - \345\217\226\346\250\241\347\261\273\357\274\210MLong & MInt \346\226\260\347\211\210\357\274\211.cpp" => "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07B - \345\217\226\346\250\241\350\277\220\347\256\227\347\261\273\357\274\210MLong & MInt\357\274\211.cpp" (95%) rename "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/05C - \345\212\250\346\200\201\345\217\226\346\250\241\347\261\273\357\274\210ModIntBase\357\274\211.cpp" => "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07C - \345\217\226\346\250\241\350\277\220\347\256\227\347\261\273\357\274\210ModIntBase\357\274\211.cpp" (90%) create mode 100644 "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07D - \345\277\253\351\200\237\345\217\226\346\250\241\350\277\220\347\256\227\347\261\273\357\274\210MontgomeryModInt32 \350\222\231\345\223\245\351\251\254\345\210\251\346\250\241\344\271\230\357\274\211.cpp" create mode 100644 "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07E - \345\244\247\346\225\260\345\277\253\351\200\237\345\217\226\346\250\241\350\277\220\347\256\227\347\261\273\357\274\210Barrett & DynModInt, with ModIntBase \345\267\264\351\233\267\347\211\271\347\272\246\345\207\217\346\250\241\344\271\230\357\274\211.cpp" rename "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07A - \347\273\204\345\220\210\346\225\260\357\274\210\345\260\217\350\214\203\345\233\264\351\242\204\345\244\204\347\220\206\357\274\214\351\200\206\345\205\203+\346\235\250\350\276\211\344\270\211\350\247\222\357\274\211.cpp" => "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/08A - \347\273\204\345\220\210\346\225\260\357\274\210\345\260\217\350\214\203\345\233\264\351\242\204\345\244\204\347\220\206\357\274\214\351\200\206\345\205\203+\346\235\250\350\276\211\344\270\211\350\247\222\357\274\211.cpp" (100%) rename "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07B - \347\273\204\345\220\210\346\225\260\357\274\210Comb, with. ModIntBase\357\274\211.cpp" => "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/08B - \347\273\204\345\220\210\346\225\260\357\274\210Comb, with. ModIntBase\357\274\211.cpp" (100%) rename "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12A - \345\244\232\351\241\271\345\274\217\357\274\210Poly\357\274\214\346\227\247\347\211\210\357\274\211.cpp" => "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12A - \345\244\232\351\241\271\345\274\217\357\274\210Poly \346\211\213\345\206\231\345\217\226\346\250\241\357\274\211.cpp" (96%) rename "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12B - \345\244\232\351\241\271\345\274\217\357\274\210Poly, with. Z\357\274\211.cpp" => "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12B - \345\244\232\351\241\271\345\274\217\357\274\210Poly, with Z\357\274\211.cpp" (95%) create mode 100644 "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12C - \345\244\232\351\241\271\345\274\217\357\274\210Poly, with MontgomeryModInt32\357\274\211.cpp" rename "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12C - \345\244\232\351\241\271\345\274\217\357\274\210Poly, with. MInt\357\274\211.cpp" => "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12D - \345\244\232\351\241\271\345\274\217\357\274\210Poly, with MInt\357\274\211.cpp" (96%) rename "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/08 - \347\264\240\346\225\260\346\265\213\350\257\225\344\270\216\345\233\240\345\274\217\345\210\206\350\247\243\357\274\210Miller-Rabin & Pollard-Rho\357\274\211.cpp" => "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/17 - \347\264\240\346\225\260\346\265\213\350\257\225\344\270\216\345\233\240\345\274\217\345\210\206\350\247\243\357\274\210Miller-Rabin & Pollard-Rho\357\274\211.cpp" (100%) rename "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/11 - \351\253\230\347\262\276\345\272\246\357\274\210BigInt\357\274\211.cpp" => "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/05 - \351\253\230\347\262\276\345\272\246\357\274\210BigInt\357\274\211.cpp" (100%) rename "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/12 - Link-Cut Tree.md" => "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/11 - Link-Cut Tree.md" (100%) rename "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/05 - \345\255\227\347\254\246\344\270\262/03A - \345\220\216\347\274\200\346\225\260\347\273\204\357\274\210SuffixArray \346\227\247\347\211\210\357\274\211.cpp" => "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/05 - \345\255\227\347\254\246\344\270\262/03A - \345\220\216\347\274\200\346\225\260\347\273\204\357\274\210SuffixArray\357\274\211.cpp" (58%) rename "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/05 - \345\255\227\347\254\246\344\270\262/03B - \345\220\216\347\274\200\346\225\260\347\273\204\357\274\210SA\345\217\212\345\205\266\345\272\224\347\224\250 \346\226\260\347\211\210\357\274\211.cpp" => "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/05 - \345\255\227\347\254\246\344\270\262/03B - \345\220\216\347\274\200\346\225\260\347\273\204\357\274\210SA\357\274\211.cpp" (95%) diff --git "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/01 - \346\235\202\347\261\273/05 - \345\277\253\350\257\273.cpp" "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/01 - \346\235\202\347\261\273/05 - \345\277\253\350\257\273.cpp" new file mode 100644 index 0000000..8f665a5 --- /dev/null +++ "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/01 - \346\235\202\347\261\273/05 - \345\277\253\350\257\273.cpp" @@ -0,0 +1,54 @@ +/** 快读 + * 2023-08-11: https://ac.nowcoder.com/acm/contest/view-submission?submissionId=63381475&returnHomeType=1&uid=815516497 + * * 感谢菜菜园子群友提供 +**/ +struct IO { + char a[1 << 25], b[1 << 25], *s, *t; + IO() : s(a), t(b) { + a[std::fread(a, 1, sizeof a, stdin)] = 0; + } + ~IO() { + std::fwrite(b, 1, t - b, stdout); + } + IO &operator>>(std::uint64_t &x); + IO &operator>>(std::int64_t &x); + IO &operator>>(std::int32_t &x); + IO &operator>>(std::uint32_t &x) { + x = 0; + + while (*s < '0' || *s > '9') + ++s; + + while (*s >= '0' && *s <= '9') + x = x * 10 + *s++ - '0'; + + return *this; + } + IO &operator<<(const char *tmp) { + return std::fwrite(tmp, 1, std::strlen(tmp), stdout), *this; + } + IO &operator<<(char x) { + return *t++ = x, *this; + } + IO &operator<<(std::int32_t x); + IO &operator<<(std::uint64_t x); + IO &operator<<(std::int64_t x); + IO &operator<<(std::uint32_t x) { + static char c[16], *i; + i = c; + + if (x == 0) { + *t++ = '0'; + } else { + while (x != 0) { + std::uint32_t y = x / 10; + *i++ = x - y * 10 + '0', x = y; + } + + while (i != c) + *t++ = *--i; + } + + return *this; + } +} io; \ No newline at end of file diff --git "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/02 - \345\233\276\344\270\216\347\275\221\347\273\234/09 - \345\234\206\346\226\271\346\240\221.cpp" "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/02 - \345\233\276\344\270\216\347\275\221\347\273\234/09 - \345\234\206\346\226\271\346\240\221.cpp" new file mode 100644 index 0000000..9d9cfef --- /dev/null +++ "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/02 - \345\233\276\344\270\216\347\275\221\347\273\234/09 - \345\234\206\346\226\271\346\240\221.cpp" @@ -0,0 +1,65 @@ +/** 圆方树(BlockCutTree) + * -: - + * * 感谢 [cnblogs @Misty7](https://www.luogu.com/user/344543) 提供 +**/ +struct BlockCutTree { + int n; + std::vector> adj; + std::vector dfn, low, stk; + int cnt, cur; + std::vector> edges; + + BlockCutTree() {} + BlockCutTree(int n) { + init(n); + } + + void init(int n) { + this->n = n; + adj.assign(n, {}); + dfn.assign(n, -1); + low.resize(n); + stk.clear(); + cnt = cur = 0; + edges.clear(); + } + + void addEdge(int u, int v) { + adj[u].push_back(v); + adj[v].push_back(u); + } + + void dfs(int x) { + stk.push_back(x); + dfn[x] = low[x] = cur++; + + for (auto y : adj[x]) { + if (dfn[y] == -1) { + dfs(y); + low[x] = std::min(low[x], low[y]); + if (low[y] == dfn[x]) { + int v; + do { + v = stk.back(); + stk.pop_back(); + edges.emplace_back(n + cnt, v); + } while (v != y); + edges.emplace_back(x, n + cnt); + cnt++; + } + } else { + low[x] = std::min(low[x], dfn[y]); + } + } + } + + std::pair>> work() { + for (int i = 0; i < n; i++) { + if (dfn[i] == -1) { + stk.clear(); + dfs(i); + } + } + return {cnt, edges}; + } +}; \ No newline at end of file diff --git "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/05A - \345\217\226\346\250\241\347\261\273\357\274\210Z \346\227\247\347\211\210\357\274\211.cpp" "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07A - \345\217\226\346\250\241\350\277\220\347\256\227\347\261\273\357\274\210Z\357\274\211.cpp" similarity index 94% rename from "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/05A - \345\217\226\346\250\241\347\261\273\357\274\210Z \346\227\247\347\211\210\357\274\211.cpp" rename to "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07A - \345\217\226\346\250\241\350\277\220\347\256\227\347\261\273\357\274\210Z\357\274\211.cpp" index e4c8c38..7b8778e 100644 --- "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/05A - \345\217\226\346\250\241\347\261\273\357\274\210Z \346\227\247\347\211\210\357\274\211.cpp" +++ "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07A - \345\217\226\346\250\241\350\277\220\347\256\227\347\261\273\357\274\210Z\357\274\211.cpp" @@ -1,4 +1,4 @@ -/** 取模类(Z 旧版) +/** 取模运算类(Z) * 2022-06-12: https://codeforces.com/contest/1697/submission/160317720 **/ constexpr int P = 998244353; diff --git "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/05B - \345\217\226\346\250\241\347\261\273\357\274\210MLong & MInt \346\226\260\347\211\210\357\274\211.cpp" "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07B - \345\217\226\346\250\241\350\277\220\347\256\227\347\261\273\357\274\210MLong & MInt\357\274\211.cpp" similarity index 95% rename from "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/05B - \345\217\226\346\250\241\347\261\273\357\274\210MLong & MInt \346\226\260\347\211\210\357\274\211.cpp" rename to "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07B - \345\217\226\346\250\241\350\277\220\347\256\227\347\261\273\357\274\210MLong & MInt\357\274\211.cpp" index 0b14b42..c0c6ceb 100644 --- "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/05B - \345\217\226\346\250\241\347\261\273\357\274\210MLong & MInt \346\226\260\347\211\210\357\274\211.cpp" +++ "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07B - \345\217\226\346\250\241\350\277\220\347\256\227\347\261\273\357\274\210MLong & MInt\357\274\211.cpp" @@ -1,4 +1,4 @@ -/** 取模类(MLong & MInt 新版) +/** 取模运算类(MLong & MInt) * 2023-08-14: https://ac.nowcoder.com/acm/contest/view-submission?submissionId=63433564 * * 根据输入内容动态修改 MOD 的方法:Z::setMod(p) 。 diff --git "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/05C - \345\212\250\346\200\201\345\217\226\346\250\241\347\261\273\357\274\210ModIntBase\357\274\211.cpp" "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07C - \345\217\226\346\250\241\350\277\220\347\256\227\347\261\273\357\274\210ModIntBase\357\274\211.cpp" similarity index 90% rename from "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/05C - \345\212\250\346\200\201\345\217\226\346\250\241\347\261\273\357\274\210ModIntBase\357\274\211.cpp" rename to "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07C - \345\217\226\346\250\241\350\277\220\347\256\227\347\261\273\357\274\210ModIntBase\357\274\211.cpp" index 88e8c2f..feb38dc 100644 --- "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/05C - \345\212\250\346\200\201\345\217\226\346\250\241\347\261\273\357\274\210ModIntBase\357\274\211.cpp" +++ "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07C - \345\217\226\346\250\241\350\277\220\347\256\227\347\261\273\357\274\210ModIntBase\357\274\211.cpp" @@ -1,5 +1,6 @@ -/** 动态取模类(ModIntBase) +/** 取模运算类(ModIntBase) * 2024-08-14: https://ac.nowcoder.com/acm/contest/view-submission?submissionId=70980889&returnHomeType=1&uid=329687984 + * 2024-10-11: https://qoj.ac/submission/629765 **/ // TODO: Dynamic ModInt @@ -30,11 +31,11 @@ template requires std::unsigned_integral struct ModIntBase { public: - constexpr ModIntBase() : x {0} {} - + constexpr ModIntBase() : x(0) {} + template requires std::integral - constexpr ModIntBase(T x_) : x {norm(x_ % T {P})} {} + constexpr ModIntBase(T x_) : x(norm(x_ % T {P})) {} constexpr static U norm(U x) { if ((x >> (8 * sizeof(U) - 1) & 1) == 1) { diff --git "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07D - \345\277\253\351\200\237\345\217\226\346\250\241\350\277\220\347\256\227\347\261\273\357\274\210MontgomeryModInt32 \350\222\231\345\223\245\351\251\254\345\210\251\346\250\241\344\271\230\357\274\211.cpp" "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07D - \345\277\253\351\200\237\345\217\226\346\250\241\350\277\220\347\256\227\347\261\273\357\274\210MontgomeryModInt32 \350\222\231\345\223\245\351\251\254\345\210\251\346\250\241\344\271\230\357\274\211.cpp" new file mode 100644 index 0000000..17db0d5 --- /dev/null +++ "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07D - \345\277\253\351\200\237\345\217\226\346\250\241\350\277\220\347\256\227\347\261\273\357\274\210MontgomeryModInt32 \350\222\231\345\223\245\351\251\254\345\210\251\346\250\241\344\271\230\357\274\211.cpp" @@ -0,0 +1,206 @@ +/** 快速取模运算类(MontgomeryModInt32 蒙哥马利模乘) + * 2023-08-11: https://ac.nowcoder.com/acm/contest/view-submission?submissionId=63381475&returnHomeType=1&uid=815516497 + * * 感谢菜菜园子群友提供 +**/ +template struct MontgomeryModInt32 { +public: + using i32 = std::int32_t; + using u32 = std::uint32_t; + using i64 = std::int64_t; + using u64 = std::uint64_t; + +private: + u32 v; + + static constexpr u32 get_r() { + u32 iv = P; + + for (u32 i = 0; i != 4; ++i) + iv *= 2U - P * iv; + + return -iv; + } + + static constexpr u32 r = get_r(), r2 = -u64(P) % P; + + static_assert((P & 1) == 1); + static_assert(-r * P == 1); + static_assert(P < (1 << 30)); + +public: + static constexpr u32 pow_mod(u32 x, u64 y) { + if ((y %= P - 1) < 0) + y += P - 1; + + u32 res = 1; + + for (; y != 0; y >>= 1, x = u64(x) * x % P) + if (y & 1) + res = u64(res) * x % P; + + return res; + } + + static constexpr u32 get_pr() { + u32 tmp[32] = {}, cnt = 0; + const u64 phi = P - 1; + u64 m = phi; + + for (u64 i = 2; i * i <= m; ++i) { + if (m % i == 0) { + tmp[cnt++] = i; + + while (m % i == 0) + m /= i; + } + } + + if (m > 1) + tmp[cnt++] = m; + + for (u64 res = 2; res <= phi; ++res) { + bool flag = true; + + for (u32 i = 0; i != cnt && flag; ++i) + flag &= pow_mod(res, phi / tmp[i]) != 1; + + if (flag) + return res; + } + + return 0; + } + + MontgomeryModInt32() = default; + ~MontgomeryModInt32() = default; + constexpr MontgomeryModInt32(u32 v) : v(reduce(u64(v) * r2)) {} + constexpr MontgomeryModInt32(const MontgomeryModInt32 &rhs) : v(rhs.v) {} + static constexpr u32 reduce(u64 x) { + return x + (u64(u32(x) * r) * P) >> 32; + } + static constexpr u32 norm(u32 x) { + return x - (P & -(x >= P)); + } + constexpr u32 get() const { + u32 res = reduce(v) - P; + return res + (P & -(res >> 31)); + } + explicit constexpr operator u32() const { + return get(); + } + explicit constexpr operator i32() const { + return i32(get()); + } + constexpr MontgomeryModInt32 &operator=(const MontgomeryModInt32 &rhs) { + return v = rhs.v, *this; + } + constexpr MontgomeryModInt32 operator-() const { + MontgomeryModInt32 res; + return res.v = (P << 1 & -(v != 0)) - v, res; + } + constexpr MontgomeryModInt32 inv() const { + return pow(-1); + } + constexpr MontgomeryModInt32 &operator+=(const MontgomeryModInt32 &rhs) { + return v += rhs.v - (P << 1), v += P << 1 & -(v >> 31), *this; + } + constexpr MontgomeryModInt32 &operator-=(const MontgomeryModInt32 &rhs) { + return v -= rhs.v, v += P << 1 & -(v >> 31), *this; + } + constexpr MontgomeryModInt32 &operator*=(const MontgomeryModInt32 &rhs) { + return v = reduce(u64(v) * rhs.v), *this; + } + constexpr MontgomeryModInt32 &operator/=(const MontgomeryModInt32 &rhs) { + return this->operator*=(rhs.inv()); + } + friend MontgomeryModInt32 operator+(const MontgomeryModInt32 &lhs, + const MontgomeryModInt32 &rhs) { + return MontgomeryModInt32(lhs) += rhs; + } + friend MontgomeryModInt32 operator-(const MontgomeryModInt32 &lhs, + const MontgomeryModInt32 &rhs) { + return MontgomeryModInt32(lhs) -= rhs; + } + friend MontgomeryModInt32 operator*(const MontgomeryModInt32 &lhs, + const MontgomeryModInt32 &rhs) { + return MontgomeryModInt32(lhs) *= rhs; + } + friend MontgomeryModInt32 operator/(const MontgomeryModInt32 &lhs, + const MontgomeryModInt32 &rhs) { + return MontgomeryModInt32(lhs) /= rhs; + } + friend bool operator==(const MontgomeryModInt32 &lhs, const MontgomeryModInt32 &rhs) { + return norm(lhs.v) == norm(rhs.v); + } + friend bool operator!=(const MontgomeryModInt32 &lhs, const MontgomeryModInt32 &rhs) { + return norm(lhs.v) != norm(rhs.v); + } + friend std::istream &operator>>(std::istream &is, MontgomeryModInt32 &rhs) { + return is >> rhs.v, rhs.v = reduce(u64(rhs.v) * r2), is; + } + friend std::ostream &operator<<(std::ostream &os, const MontgomeryModInt32 &rhs) { + return os << rhs.get(); + } + constexpr MontgomeryModInt32 pow(i64 y) const { + if ((y %= P - 1) < 0) + y += P - 1; // phi(P) = P - 1, assume P is a prime number + + MontgomeryModInt32 res(1), x(*this); + + for (; y != 0; y >>= 1, x *= x) + if (y & 1) + res *= x; + + return res; + } +}; + +template MontgomeryModInt32

sqrt(const MontgomeryModInt32

&x) { + using value_type = MontgomeryModInt32

; + static constexpr value_type negtive_one(P - 1), ZERO(0); + + if (x == ZERO || x.pow(P - 1 >> 1) == negtive_one) + return ZERO; + + if ((P & 3) == 3) + return x.pow(P + 1 >> 2); + + static value_type w2, ax; + ax = x; + static std::random_device rd; + static std::mt19937 gen(rd()); + static std::uniform_int_distribution dis(1, P - 1); + const value_type four(value_type(4) * x); + static value_type t; + + do + t = value_type(dis(gen)), w2 = t * t - four; + + while (w2.pow(P - 1 >> 1) != negtive_one); + + struct Field_P2 { // (A + Bx)(C+Dx)=(AC-BDa)+(AD+BC+BDt)x + public: + value_type a, b; + Field_P2(const value_type &a, const value_type &b) : a(a), b(b) {} + ~Field_P2() = default; + Field_P2 &operator*=(const Field_P2 &rhs) { + value_type tmp1(b * rhs.b), tmp2(a * rhs.a - tmp1 * ax), + tmp3(a * rhs.b + b * rhs.a + tmp1 * t); + return a = tmp2, b = tmp3, *this; + } + Field_P2 pow(std::uint64_t y) const { + Field_P2 res(value_type(1), ZERO), x(*this); + + for (; y != 0; y >>= 1, x *= x) + if (y & 1) + res *= x; + + return res; + } + } res(ZERO, value_type(1)); + return res.pow(P + 1 >> 1).a; +} + +std::uint64_t get_len(std::uint64_t n) { // if n=0, boom + return --n, n |= n >> 1, n |= n >> 2, n |= n >> 4, n |= n >> 8, n |= n >> 16, n |= n >> 32, ++n; +} \ No newline at end of file diff --git "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07E - \345\244\247\346\225\260\345\277\253\351\200\237\345\217\226\346\250\241\350\277\220\347\256\227\347\261\273\357\274\210Barrett & DynModInt, with ModIntBase \345\267\264\351\233\267\347\211\271\347\272\246\345\207\217\346\250\241\344\271\230\357\274\211.cpp" "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07E - \345\244\247\346\225\260\345\277\253\351\200\237\345\217\226\346\250\241\350\277\220\347\256\227\347\261\273\357\274\210Barrett & DynModInt, with ModIntBase \345\267\264\351\233\267\347\211\271\347\272\246\345\207\217\346\250\241\344\271\230\357\274\211.cpp" new file mode 100644 index 0000000..afe7e21 --- /dev/null +++ "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07E - \345\244\247\346\225\260\345\277\253\351\200\237\345\217\226\346\250\241\350\277\220\347\256\227\347\261\273\357\274\210Barrett & DynModInt, with ModIntBase \345\267\264\351\233\267\347\211\271\347\272\246\345\207\217\346\250\241\344\271\230\357\274\211.cpp" @@ -0,0 +1,286 @@ +/** 大数快速动态取模类(Barrett & DynModInt, with ModIntBase) + * 2024-10-22: https://qoj.ac/submission/665008 + * 2024-11-06: https://qoj.ac/submission/716968 +**/ +using u32 = unsigned; +using u64 = unsigned long long; +using u128 = unsigned __int128; +template +constexpr T power(T a, u64 b, T res = 1) { + for (; b != 0; b /= 2, a *= a) { + if (b & 1) { + res *= a; + } + } + return res; +} + +template +constexpr u32 mulMod(u32 a, u32 b) { + return u64(a) * b % P; +} + +template +constexpr u64 mulMod(u64 a, u64 b) { + u64 res = a * b - u64(1.L * a * b / P - 0.5L) * P; + res %= P; + return res; +} + +constexpr i64 safeMod(i64 x, i64 m) { + x %= m; + if (x < 0) { + x += m; + } + return x; +} + +constexpr std::pair invGcd(i64 a, i64 b) { + a = safeMod(a, b); + if (a == 0) { + return {b, 0}; + } + + i64 s = b, t = a; + i64 m0 = 0, m1 = 1; + + while (t) { + i64 u = s / t; + s -= t * u; + m0 -= m1 * u; + + std::swap(s, t); + std::swap(m0, m1); + } + + if (m0 < 0) { + m0 += b / s; + } + + return {s, m0}; +} + +template +struct ModIntBase { +public: + constexpr ModIntBase() : x(0) {} + template + constexpr ModIntBase(T x_) : x(x_ % mod()) {} + template + constexpr ModIntBase(T x_) { + using S = std::make_signed_t; + S v = x_ % S(mod()); + if (v < 0) { + v += mod(); + } + x = v; + } + + constexpr static U mod() { + return P; + } + + constexpr U val() const { + return x; + } + + constexpr ModIntBase operator-() const { + ModIntBase res; + res.x = (x == 0 ? 0 : mod() - x); + return res; + } + + constexpr ModIntBase inv() const { + return power(*this, mod() - 2); + } + + constexpr ModIntBase &operator*=(const ModIntBase &rhs) & { + x = mulMod(x, rhs.val()); + return *this; + } + constexpr ModIntBase &operator+=(const ModIntBase &rhs) & { + x += rhs.val(); + if (x >= mod()) { + x -= mod(); + } + return *this; + } + constexpr ModIntBase &operator-=(const ModIntBase &rhs) & { + x -= rhs.val(); + if (x >= mod()) { + x += mod(); + } + return *this; + } + constexpr ModIntBase &operator/=(const ModIntBase &rhs) & { + return *this *= rhs.inv(); + } + + friend constexpr ModIntBase operator*(ModIntBase lhs, const ModIntBase &rhs) { + lhs *= rhs; + return lhs; + } + friend constexpr ModIntBase operator+(ModIntBase lhs, const ModIntBase &rhs) { + lhs += rhs; + return lhs; + } + friend constexpr ModIntBase operator-(ModIntBase lhs, const ModIntBase &rhs) { + lhs -= rhs; + return lhs; + } + friend constexpr ModIntBase operator/(ModIntBase lhs, const ModIntBase &rhs) { + lhs /= rhs; + return lhs; + } + + friend constexpr std::istream &operator>>(std::istream &is, ModIntBase &a) { + i64 i; + is >> i; + a = i; + return is; + } + friend constexpr std::ostream &operator<<(std::ostream &os, const ModIntBase &a) { + return os << a.val(); + } + + friend constexpr std::strong_ordering operator<=>(ModIntBase lhs, ModIntBase rhs) { + return lhs.val() <=> rhs.val(); + } + +private: + U x; +}; + +template +using ModInt = ModIntBase; +template +using ModInt64 = ModIntBase; + +struct Barrett { +public: + Barrett(u32 m_) : m(m_), im((u64)(-1) / m_ + 1) {} + + constexpr u32 mod() const { + return m; + } + + constexpr u32 mul(u32 a, u32 b) const { + u64 z = a; + z *= b; + + u64 x = u64((u128(z) * im) >> 64); + + u32 v = u32(z - x * m); + if (m <= v) { + v += m; + } + return v; + } + +private: + u32 m; + u64 im; +}; + +template +struct DynModInt { +public: + constexpr DynModInt() : x(0) {} + template + constexpr DynModInt(T x_) : x(x_ % mod()) {} + template + constexpr DynModInt(T x_) { + int v = x_ %= int(mod()); + if (v < 0) { + v += mod(); + } + x = v; + } + + constexpr static void setMod(u32 m) { + bt = m; + } + + static u32 mod() { + return bt.mod(); + } + + constexpr u32 val() const { + return x; + } + + constexpr DynModInt operator-() const { + DynModInt res; + res.x = (x == 0 ? 0 : mod() - x); + return res; + } + + constexpr DynModInt inv() const { + auto v = invGcd(x, mod()); + assert(v.first == 1); + return v.second; + } + + constexpr DynModInt &operator*=(const DynModInt &rhs) & { + x = bt.mul(x, rhs.val()); + return *this; + } + constexpr DynModInt &operator+=(const DynModInt &rhs) & { + x += rhs.val(); + if (x >= mod()) { + x -= mod(); + } + return *this; + } + constexpr DynModInt &operator-=(const DynModInt &rhs) & { + x -= rhs.val(); + if (x >= mod()) { + x += mod(); + } + return *this; + } + constexpr DynModInt &operator/=(const DynModInt &rhs) & { + return *this *= rhs.inv(); + } + + friend constexpr DynModInt operator*(DynModInt lhs, const DynModInt &rhs) { + lhs *= rhs; + return lhs; + } + friend constexpr DynModInt operator+(DynModInt lhs, const DynModInt &rhs) { + lhs += rhs; + return lhs; + } + friend constexpr DynModInt operator-(DynModInt lhs, const DynModInt &rhs) { + lhs -= rhs; + return lhs; + } + friend constexpr DynModInt operator/(DynModInt lhs, const DynModInt &rhs) { + lhs /= rhs; + return lhs; + } + + friend constexpr std::istream &operator>>(std::istream &is, DynModInt &a) { + i64 i; + is >> i; + a = i; + return is; + } + friend constexpr std::ostream &operator<<(std::ostream &os, const DynModInt &a) { + return os << a.val(); + } + + friend constexpr std::strong_ordering operator<=>(DynModInt lhs, DynModInt rhs) { + return lhs.val() <=> rhs.val(); + } + +private: + u32 x; + static Barrett bt; +}; + +template +Barrett DynModInt::bt = 998244353; + +// using Z = ModInt<1000000007>; +using Z = DynModInt<0>; \ No newline at end of file diff --git "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07A - \347\273\204\345\220\210\346\225\260\357\274\210\345\260\217\350\214\203\345\233\264\351\242\204\345\244\204\347\220\206\357\274\214\351\200\206\345\205\203+\346\235\250\350\276\211\344\270\211\350\247\222\357\274\211.cpp" "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/08A - \347\273\204\345\220\210\346\225\260\357\274\210\345\260\217\350\214\203\345\233\264\351\242\204\345\244\204\347\220\206\357\274\214\351\200\206\345\205\203+\346\235\250\350\276\211\344\270\211\350\247\222\357\274\211.cpp" similarity index 100% rename from "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07A - \347\273\204\345\220\210\346\225\260\357\274\210\345\260\217\350\214\203\345\233\264\351\242\204\345\244\204\347\220\206\357\274\214\351\200\206\345\205\203+\346\235\250\350\276\211\344\270\211\350\247\222\357\274\211.cpp" rename to "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/08A - \347\273\204\345\220\210\346\225\260\357\274\210\345\260\217\350\214\203\345\233\264\351\242\204\345\244\204\347\220\206\357\274\214\351\200\206\345\205\203+\346\235\250\350\276\211\344\270\211\350\247\222\357\274\211.cpp" diff --git "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07B - \347\273\204\345\220\210\346\225\260\357\274\210Comb, with. ModIntBase\357\274\211.cpp" "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/08B - \347\273\204\345\220\210\346\225\260\357\274\210Comb, with. ModIntBase\357\274\211.cpp" similarity index 100% rename from "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/07B - \347\273\204\345\220\210\346\225\260\357\274\210Comb, with. ModIntBase\357\274\211.cpp" rename to "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/08B - \347\273\204\345\220\210\346\225\260\357\274\210Comb, with. ModIntBase\357\274\211.cpp" diff --git "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12A - \345\244\232\351\241\271\345\274\217\357\274\210Poly\357\274\214\346\227\247\347\211\210\357\274\211.cpp" "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12A - \345\244\232\351\241\271\345\274\217\357\274\210Poly \346\211\213\345\206\231\345\217\226\346\250\241\357\274\211.cpp" similarity index 96% rename from "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12A - \345\244\232\351\241\271\345\274\217\357\274\210Poly\357\274\214\346\227\247\347\211\210\357\274\211.cpp" rename to "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12A - \345\244\232\351\241\271\345\274\217\357\274\210Poly \346\211\213\345\206\231\345\217\226\346\250\241\357\274\211.cpp" index 7493422..c493616 100644 --- "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12A - \345\244\232\351\241\271\345\274\217\357\274\210Poly\357\274\214\346\227\247\347\211\210\357\274\211.cpp" +++ "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12A - \345\244\232\351\241\271\345\274\217\357\274\210Poly \346\211\213\345\206\231\345\217\226\346\250\241\357\274\211.cpp" @@ -1,4 +1,4 @@ -/** 多项式(Poly,旧版) +/** 多项式(Poly 手写取模) * 2021-06-16: https://codeforces.com/gym/103119/submission/119653035 **/ constexpr int C = 1024; diff --git "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12B - \345\244\232\351\241\271\345\274\217\357\274\210Poly, with. Z\357\274\211.cpp" "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12B - \345\244\232\351\241\271\345\274\217\357\274\210Poly, with Z\357\274\211.cpp" similarity index 95% rename from "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12B - \345\244\232\351\241\271\345\274\217\357\274\210Poly, with. Z\357\274\211.cpp" rename to "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12B - \345\244\232\351\241\271\345\274\217\357\274\210Poly, with Z\357\274\211.cpp" index b3ec344..2d80d82 100644 --- "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12B - \345\244\232\351\241\271\345\274\217\357\274\210Poly, with. Z\357\274\211.cpp" +++ "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12B - \345\244\232\351\241\271\345\274\217\357\274\210Poly, with Z\357\274\211.cpp" @@ -1,4 +1,4 @@ -/** 多项式(Poly, with. Z) +/** 多项式(Poly, with Z) * 2023-02-06: https://atcoder.jp/contests/arc155/submissions/38664055 **/ constexpr int P = 998244353; diff --git "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12C - \345\244\232\351\241\271\345\274\217\357\274\210Poly, with MontgomeryModInt32\357\274\211.cpp" "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12C - \345\244\232\351\241\271\345\274\217\357\274\210Poly, with MontgomeryModInt32\357\274\211.cpp" new file mode 100644 index 0000000..2fc05cb --- /dev/null +++ "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12C - \345\244\232\351\241\271\345\274\217\357\274\210Poly, with MontgomeryModInt32\357\274\211.cpp" @@ -0,0 +1,863 @@ +/** 多项式(Poly, with MontgomeryModInt32) + * 2023-08-11: https://ac.nowcoder.com/acm/contest/view-submission?submissionId=63381475&returnHomeType=1&uid=815516497 + * * 感谢菜菜园子群友提供 +**/ +template struct MontgomeryModInt32 { +public: + using i32 = std::int32_t; + using u32 = std::uint32_t; + using i64 = std::int64_t; + using u64 = std::uint64_t; + +private: + u32 v; + + static constexpr u32 get_r() { + u32 iv = P; + + for (u32 i = 0; i != 4; ++i) + iv *= 2U - P * iv; + + return -iv; + } + + static constexpr u32 r = get_r(), r2 = -u64(P) % P; + + static_assert((P & 1) == 1); + static_assert(-r * P == 1); + static_assert(P < (1 << 30)); + +public: + static constexpr u32 pow_mod(u32 x, u64 y) { + if ((y %= P - 1) < 0) + y += P - 1; + + u32 res = 1; + + for (; y != 0; y >>= 1, x = u64(x) * x % P) + if (y & 1) + res = u64(res) * x % P; + + return res; + } + + static constexpr u32 get_pr() { + u32 tmp[32] = {}, cnt = 0; + const u64 phi = P - 1; + u64 m = phi; + + for (u64 i = 2; i * i <= m; ++i) { + if (m % i == 0) { + tmp[cnt++] = i; + + while (m % i == 0) + m /= i; + } + } + + if (m > 1) + tmp[cnt++] = m; + + for (u64 res = 2; res <= phi; ++res) { + bool flag = true; + + for (u32 i = 0; i != cnt && flag; ++i) + flag &= pow_mod(res, phi / tmp[i]) != 1; + + if (flag) + return res; + } + + return 0; + } + + MontgomeryModInt32() = default; + ~MontgomeryModInt32() = default; + constexpr MontgomeryModInt32(u32 v) : v(reduce(u64(v) * r2)) {} + constexpr MontgomeryModInt32(const MontgomeryModInt32 &rhs) : v(rhs.v) {} + static constexpr u32 reduce(u64 x) { + return x + (u64(u32(x) * r) * P) >> 32; + } + static constexpr u32 norm(u32 x) { + return x - (P & -(x >= P)); + } + constexpr u32 get() const { + u32 res = reduce(v) - P; + return res + (P & -(res >> 31)); + } + explicit constexpr operator u32() const { + return get(); + } + explicit constexpr operator i32() const { + return i32(get()); + } + constexpr MontgomeryModInt32 &operator=(const MontgomeryModInt32 &rhs) { + return v = rhs.v, *this; + } + constexpr MontgomeryModInt32 operator-() const { + MontgomeryModInt32 res; + return res.v = (P << 1 & -(v != 0)) - v, res; + } + constexpr MontgomeryModInt32 inv() const { + return pow(-1); + } + constexpr MontgomeryModInt32 &operator+=(const MontgomeryModInt32 &rhs) { + return v += rhs.v - (P << 1), v += P << 1 & -(v >> 31), *this; + } + constexpr MontgomeryModInt32 &operator-=(const MontgomeryModInt32 &rhs) { + return v -= rhs.v, v += P << 1 & -(v >> 31), *this; + } + constexpr MontgomeryModInt32 &operator*=(const MontgomeryModInt32 &rhs) { + return v = reduce(u64(v) * rhs.v), *this; + } + constexpr MontgomeryModInt32 &operator/=(const MontgomeryModInt32 &rhs) { + return this->operator*=(rhs.inv()); + } + friend MontgomeryModInt32 operator+(const MontgomeryModInt32 &lhs, + const MontgomeryModInt32 &rhs) { + return MontgomeryModInt32(lhs) += rhs; + } + friend MontgomeryModInt32 operator-(const MontgomeryModInt32 &lhs, + const MontgomeryModInt32 &rhs) { + return MontgomeryModInt32(lhs) -= rhs; + } + friend MontgomeryModInt32 operator*(const MontgomeryModInt32 &lhs, + const MontgomeryModInt32 &rhs) { + return MontgomeryModInt32(lhs) *= rhs; + } + friend MontgomeryModInt32 operator/(const MontgomeryModInt32 &lhs, + const MontgomeryModInt32 &rhs) { + return MontgomeryModInt32(lhs) /= rhs; + } + friend bool operator==(const MontgomeryModInt32 &lhs, const MontgomeryModInt32 &rhs) { + return norm(lhs.v) == norm(rhs.v); + } + friend bool operator!=(const MontgomeryModInt32 &lhs, const MontgomeryModInt32 &rhs) { + return norm(lhs.v) != norm(rhs.v); + } + friend std::istream &operator>>(std::istream &is, MontgomeryModInt32 &rhs) { + return is >> rhs.v, rhs.v = reduce(u64(rhs.v) * r2), is; + } + friend std::ostream &operator<<(std::ostream &os, const MontgomeryModInt32 &rhs) { + return os << rhs.get(); + } + constexpr MontgomeryModInt32 pow(i64 y) const { + if ((y %= P - 1) < 0) + y += P - 1; // phi(P) = P - 1, assume P is a prime number + + MontgomeryModInt32 res(1), x(*this); + + for (; y != 0; y >>= 1, x *= x) + if (y & 1) + res *= x; + + return res; + } +}; + +template MontgomeryModInt32

sqrt(const MontgomeryModInt32

&x) { + using value_type = MontgomeryModInt32

; + static constexpr value_type negtive_one(P - 1), ZERO(0); + + if (x == ZERO || x.pow(P - 1 >> 1) == negtive_one) + return ZERO; + + if ((P & 3) == 3) + return x.pow(P + 1 >> 2); + + static value_type w2, ax; + ax = x; + static std::random_device rd; + static std::mt19937 gen(rd()); + static std::uniform_int_distribution dis(1, P - 1); + const value_type four(value_type(4) * x); + static value_type t; + + do + t = value_type(dis(gen)), w2 = t * t - four; + + while (w2.pow(P - 1 >> 1) != negtive_one); + + struct Field_P2 { // (A + Bx)(C+Dx)=(AC-BDa)+(AD+BC+BDt)x + public: + value_type a, b; + Field_P2(const value_type &a, const value_type &b) : a(a), b(b) {} + ~Field_P2() = default; + Field_P2 &operator*=(const Field_P2 &rhs) { + value_type tmp1(b * rhs.b), tmp2(a * rhs.a - tmp1 * ax), + tmp3(a * rhs.b + b * rhs.a + tmp1 * t); + return a = tmp2, b = tmp3, *this; + } + Field_P2 pow(std::uint64_t y) const { + Field_P2 res(value_type(1), ZERO), x(*this); + + for (; y != 0; y >>= 1, x *= x) + if (y & 1) + res *= x; + + return res; + } + } res(ZERO, value_type(1)); + return res.pow(P + 1 >> 1).a; +} + +std::uint64_t get_len(std::uint64_t n) { // if n=0, boom + return --n, n |= n >> 1, n |= n >> 2, n |= n >> 4, n |= n >> 8, n |= n >> 16, n |= n >> 32, ++n; +} + + +template struct NTT { +public: + using i32 = std::int32_t; + using u32 = std::uint32_t; + using i64 = std::int64_t; + using u64 = std::uint64_t; + using value_type = MontgomeryModInt32

; + +private: + static inline value_type ROOT[1 << 20], IROOT[1 << 20]; + +public: + NTT() = delete; + static void idft(i32 n, value_type x[]) { + for (i32 i = 2; i < n; i <<= 1) { + for (i32 j = 0, l = i >> 1; j != l; ++j) { + value_type u = x[j], v = x[j + l]; + x[j] = u + v, x[j + l] = u - v; + } + + for (i32 j = i, l = i >> 1, m = 1; j != n; j += i, ++m) { + value_type root = IROOT[m]; + + for (i32 k = 0; k != l; ++k) { + value_type u = x[j + k], v = x[j + k + l]; + x[j + k] = u + v, x[j + k + l] = (u - v) * root; + } + } + } + + value_type iv(P - (P - 1) / n); + + for (i32 j = 0, l = n >> 1; j != l; ++j) { + value_type u = x[j] * iv, v = x[j + l] * iv; + x[j] = u + v, x[j + l] = u - v; + } + } + static void dft(i32 n, value_type x[]) { + static i32 lim = 0; + static constexpr u32 pr = value_type::get_pr(); + static_assert(pr != 0); + static constexpr value_type G(pr); + + if (lim == 0) { + ROOT[1 << 19] = G.pow(P - 1 >> 21), IROOT[1 << 19] = G.pow(-i32(P - 1 >> 21)); + + for (i32 i = 18; i != -1; --i) + ROOT[1 << i] = ROOT[1 << i + 1] * ROOT[1 << i + 1], + IROOT[1 << i] = IROOT[1 << i + 1] * IROOT[1 << i + 1]; + + lim = 1; + } + + while ((lim << 1) < n) { + for (i32 i = lim + 1, e = lim << 1; i < e; ++i) + ROOT[i] = ROOT[i - lim] * ROOT[lim], IROOT[i] = IROOT[i - lim] * IROOT[lim]; + + lim <<= 1; + } + + for (i32 j = 0, l = n >> 1; j != l; ++j) { + value_type u = x[j], v = x[j + l]; + x[j] = u + v, x[j + l] = u - v; + } + + for (i32 i = n >> 1; i >= 2; i >>= 1) { + for (i32 j = 0, l = i >> 1; j != l; ++j) { + value_type u = x[j], v = x[j + l]; + x[j] = u + v, x[j + l] = u - v; + } + + for (i32 j = i, l = i >> 1, m = 1; j != n; j += i, ++m) { + value_type root = ROOT[m]; + + for (i32 k = 0; k != l; ++k) { + value_type u = x[j + k], v = x[j + k + l] * root; + x[j + k] = u + v, x[j + k + l] = u - v; + } + } + } + } +}; + +template void dft(std::uint32_t n, MontgomeryModInt32

x[]) { + NTT

::dft(n, x); +} + +template void idft(std::uint32_t n, MontgomeryModInt32

x[]) { + NTT

::idft(n, x); +} + +template +std::vector> add(const std::vector> &x, +const std::vector> &y) { + using i32 = std::int32_t; + using value_type = MontgomeryModInt32

; + std::vector res(std::max(x.size(), y.size())); + + for (i32 i = 0, e = std::min(x.size(), y.size()); i != e; ++i) + res[i] = x[i] + y[i]; + + if (x.size() < y.size()) + std::copy(y.begin() + x.size(), y.end(), res.begin() + x.size()); + else + std::copy(x.begin() + y.size(), x.end(), res.begin() + y.size()); + + return res; +} + +template +std::vector> sub(const std::vector> &x, +const std::vector> &y) { + using i32 = std::int32_t; + using value_type = MontgomeryModInt32

; + std::vector res(std::max(x.size(), y.size())); + + for (i32 i = 0, e = std::min(x.size(), y.size()); i != e; ++i) + res[i] = x[i] - y[i]; + + if (x.size() < y.size()) + for (i32 i = x.size(), e = y.size(); i != e; ++i) + res[i] = -y[i]; + else + std::copy(x.begin() + y.size(), x.end(), res.begin() + y.size()); + + return res; +} + +template +std::vector> mul(const std::vector> &x, +const std::vector> &y) { + using i32 = std::int32_t; + using value_type = MontgomeryModInt32

; + static value_type a[1 << 21], b[1 << 21]; + std::vector res(x.size() + y.size() - 1); + + if (std::min(x.size(), y.size()) <= 8) { + i32 n = x.size(), m = y.size(); + std::fill(res.begin(), res.end(), 0); + + for (i32 i = 0; i != n; ++i) + for (i32 j = 0; j != m; ++j) + res[i + j] += x[i] * y[j]; + } else { + std::copy(x.begin(), x.end(), a); + std::copy(y.begin(), y.end(), b); + i32 old_size = res.size(), len = get_len(old_size); + std::fill(a + x.size(), a + len, 0); + std::fill(b + y.size(), b + len, 0); + dft(len, a), dft(len, b); + res.resize(len); + + for (i32 i = 0; i != len; ++i) + res[i] = a[i] * b[i]; + + idft(len, res.data()); + res.resize(old_size); + } + + return res; +} + +template +std::vector> inv(std::vector> x) { + assert(!x.empty()); + using value_type = MontgomeryModInt32

; + using i32 = std::int32_t; + static value_type a[1 << 21], b[1 << 21]; + i32 n = x.size(), len = get_len(n); + x.resize(len); + std::vector res(len, 0); + res[0] = x[0].inv(); + + for (i32 i = 1; i != 32 && i < n; ++i) { + value_type sum(0); + + for (i32 j = 1; j <= i; ++j) + sum += x[j] * res[i - j]; + + res[i] = -res[0] * sum; + } + + for (i32 i = 64; i <= len; i <<= 1) { + std::copy_n(x.begin(), i, a); + std::copy_n(res.begin(), i, b); + dft(i, a), dft(i, b); + + for (i32 j = 0; j != i; ++j) + a[j] *= b[j]; + + idft(i, a); + std::fill_n(a, i >> 1, 0); + dft(i, a); + + for (i32 j = 0; j != i; ++j) + a[j] *= b[j]; + + idft(i, a); + + for (i32 j = i >> 1; j != i; ++j) + res[j] = -a[j]; + } + + return res.resize(n), res; +} + +template +std::vector> quo(std::vector> x, +std::vector> y) { + assert(!x.empty()); + assert(!y.empty()); + + if (x.size() == 1) + return {x[0] *y[0].inv()}; + + using value_type = MontgomeryModInt32

; + + using i32 = std::int32_t; + + static value_type a[1 << 21], b[1 << 21], c[1 << 21]; + + i32 n = x.size(), len = get_len(n); + + x.resize(len), y.resize(len, 0); + + std::vector g0 = inv(std::vector(y.begin(), y.begin() + (len >> 1))), + res(n); + + std::copy_n(g0.begin(), len >> 1, a); // a->g0 + + std::copy_n(x.begin(), len >> 1, b); + + std::fill_n(a + (len >> 1), len >> 1, 0); + + std::fill_n(b + (len >> 1), len >> 1, 0); + + dft(len, a), dft(len, b); + + for (i32 i = 0; i != len; ++i) + b[i] *= a[i]; + + idft(len, b); + std::fill_n(b + (len >> 1), len >> 1, 0); // b->q0 + std::copy_n(b, len >> 1, res.begin()); // res->q0 + std::copy_n(y.begin(), len, c); // c->y + dft(len, b), dft(len, c); + + for (i32 i = 0; i != len; ++i) + c[i] *= b[i]; + + idft(len, c); + std::fill_n(c, len >> 1, 0); + + for (i32 i = len >> 1; i != len; ++i) + c[i] = x[i] - c[i]; + + dft(len, c); + + for (i32 i = 0; i != len; ++i) + c[i] *= a[i]; + + idft(len, c); + std::copy(c + (len >> 1), c + n, res.begin() + (len >> 1)); + return res; +} + +template +std::vector> quorem(std::vector> x, +std::vector> y) { + using i32 = std::int32_t; + using value_type = MontgomeryModInt32

; + + if (x.size() < y.size()) + return {0}; + + i32 n = x.size() - y.size() + 1; + + std::reverse(x.begin(), x.end()); + + std::reverse(y.begin(), y.end()); + + x.resize(n); + + std::vector res = quo(x, y); + + std::reverse(res.begin(), res.end()); + + return res; +} + +template +std::pair>, std::vector>> quo_with_rem( + const std::vector> &x, +const std::vector> &y) { + using i32 = std::int32_t; + using value_type = MontgomeryModInt32

; + static value_type a[1 << 21], b[1 << 21]; + + if (x.size() < y.size()) + return {{0}, x}; + + std::vector q = quorem(x, y); + + if (y.size() == 1) + return {q, {0}}; + + i32 len = get_len(std::max(q.size(), y.size())), overlap = q.size() + y.size() - 1 - len; + + std::copy_n(q.begin(), q.size(), a); + + std::copy_n(y.begin(), y.size(), b); + + std::fill(a + q.size(), a + len, 0); + + std::fill(b + y.size(), b + len, 0); + + dft(len, a), dft(len, b); + + for (i32 i = 0; i != len; ++i) + a[i] *= b[i]; + + idft(len, a); + std::vector rem(y.size() - 1); + + if (overlap > 0) + for (i32 i = 0, e = rem.size(); i != overlap && i != e; ++i) + a[i] -= x[len + i]; + + for (i32 i = 0, e = rem.size(); i != e; ++i) + rem[i] = x[i] - a[i]; + + return {q, rem}; +} + +template +std::vector> rem(const std::vector> &x, +const std::vector> &y) { + return quo_with_rem(x, y).second; +} + +template +std::vector> deriv(const std::vector> &x) { + using i32 = std::int32_t; + using value_type = MontgomeryModInt32

; + + if (x.size() == 1) + return {0}; + + std::vector res(x.size() - 1); + + for (i32 i = 1, e = x.size(); i != e; ++i) + res[i - 1] = x[i] * value_type(i); + + return res; +} + +template +std::vector> integr(const std::vector> &x) { + using i32 = std::int32_t; + using value_type = MontgomeryModInt32

; + static i32 lim = 0; + static value_type INV[1 << 21]; + i32 len = x.size() + 1; + std::vector res(len); + res[0] = 0; + + if (lim < len) { + INV[1] = 1; + + for (i32 i = (lim < 2 ? 2 : lim); i < len; ++i) + INV[i] = value_type(P - P / i) * INV[P % i]; + + lim = len; + } + + for (i32 i = 1; i != len; ++i) + res[i] = x[i - 1] * INV[i]; + + return res; +} + +template +std::vector> log(const std::vector> &x) { + return x.size() == 1 ? std::vector> {0} : + integr(quo(deriv(x), x)); +} + +template +std::vector> exp(std::vector> x) { + assert(x[0] == 0); + using i32 = std::int32_t; + using value_type = MontgomeryModInt32

; + i32 n = x.size(), len = get_len(n); + + if (n == 1) + return {1}; + + static value_type a[1 << 21], b[1 << 21], c[1 << 21], d[1 << 21], e[1 << 21], f[1 << 21], + INV[1 << 21]; + + static i32 lim = 0; + + if (lim < len) { + INV[1] = 1; + + for (i32 i = (lim < 2 ? 2 : lim); i < len; ++i) + INV[i] = value_type(P - P / i) * INV[P % i]; + + lim = len; + } + + static constexpr value_type ZERO(0); + x.resize(len); + std::vector res(len); + res[0] = 1, res[1] = x[1]; + std::fill_n(a, len, 0); + std::fill_n(c, len, 0); + a[0] = 1, a[1] = -res[1]; // a->h0 + + for (i32 i = 1; i != len; ++i) + b[i - 1] = value_type(i) * x[i]; // b->f' + + std::copy_n(res.begin(), 2, c); // c->g0 + dft(4, c); // c-> dft g0 + f[0] = res[1]; + + for (i32 i = 4; i <= len; i <<= 1) { + for (i32 j = i >> 2; j != i >> 1; ++j) + f[j - 1] = res[j] * value_type(j); + + std::copy_n(b, (i >> 1) - 1, d); // d->f0' + std::fill(d + (i >> 1) - 1, d + i, ZERO); + dft(i >> 1, d); + + for (i32 j = 0; j != i >> 1; ++j) + d[j] *= c[j]; + + idft(i >> 1, d); // d->g0f0' + + for (i32 j = 0; j != (i >> 1) - 2; ++j) + d[j + (i >> 1)] = f[j] - d[j], d[j] = ZERO; + + d[(i >> 1) - 2] -= f[(i >> 1) - 2]; + d[(i >> 1) - 1] = -d[(i >> 1) - 1]; + std::copy_n(a, i, e); // e->h0 + dft(i, e), dft(i, d); + + for (i32 j = 0; j != i; ++j) + d[j] *= e[j]; + + idft(i, d); // d->h0(g0'-g0f0') + std::vector it(i); + + for (i32 j = i >> 1; j != i; ++j) + it[j] = d[j - 1] * INV[j] - x[j]; + + std::fill_n(it.begin(), i >> 1, ZERO); + dft(i, it.data()); + + for (i32 j = 0; j != i; ++j) + c[j] *= it[j]; + + idft(i, c); + + for (i32 j = i >> 1; j != i; ++j) + res[j] = -c[j]; + + if (i != len) { + std::copy_n(res.begin(), i, c); + dft(i << 1, c); + + for (i32 j = 0; j != i; ++j) + d[j] = c[j] * e[j]; + + idft(i, d); + std::fill_n(d, i >> 1, ZERO); + dft(i, d); + + for (i32 j = 0; j != i; ++j) + d[j] *= e[j]; + + idft(i, d); + + for (i32 j = i >> 1; j != i; ++j) + a[j] = -d[j]; + } + } + + return res.resize(n), res; +} + +template +std::vector> sqrt(std::vector> x) { + using i32 = std::int32_t; + using value_type = MontgomeryModInt32

; + static value_type a[1 << 21], b[1 << 21], c[1 << 21], d[1 << 21]; + static constexpr value_type iv2(P - (P - 1 >> 1)), ZERO(0); + i32 n = x.size(), len = get_len(n); + x.resize(len); + std::vector res(len); + std::uint32_t k = std::uint32_t(sqrt(x[0])); + assert(k != 0); + res[0] = std::min(P - k, k); + std::fill_n(a, len, 0); + a[0] = res[0].inv(); // a->h0 + b[0] = res[0], b[1] = ZERO; // b->g0 + dft(2, b); // b-> dft g0 + + for (i32 i = 2; i <= len; i <<= 1) { + for (i32 j = 0; j != i >> 1; ++j) + c[j] = b[j] * b[j]; + + idft(i >> 1, c); + + for (i32 j = 0; j != (i >> 1) - 1; ++j) + c[j + (i >> 1)] = c[j] - x[j] - x[j + (i >> 1)], c[j] = ZERO; + + c[(i >> 1) - 1] -= x[(i >> 1) - 1]; + c[i - 1] -= x[i - 1]; + std::copy_n(a, i, d); // d->h0 + dft(i, d), dft(i, c); + + for (i32 j = 0; j != i; ++j) + c[j] *= d[j]; + + idft(i, c); + + for (i32 j = i >> 1; j != i; ++j) + res[j] = -c[j] * iv2; + + if (i != len) { + std::copy_n(res.begin(), i, b); + dft(i, b); // b-> dft g0 + + for (i32 j = 0; j != i; ++j) + c[j] = b[j] * d[j]; + + idft(i, c); + std::fill_n(c, i >> 1, ZERO); + dft(i, c); + + for (i32 j = 0; j != i; ++j) + c[j] *= d[j]; + + idft(i, c); + + for (i32 j = i >> 1; j != i; ++j) + a[j] = -c[j]; + } + } + + return res.resize(n), res; +} + +template +std::vector> sqrtinv(std::vector> x) { + using i32 = std::int32_t; + using value_type = MontgomeryModInt32

; + static value_type a[1 << 21], b[1 << 21], c[1 << 21], d[1 << 21]; + static constexpr value_type iv2(P - (P - 1 >> 1)), ZERO(0); + i32 n = x.size(), len = get_len(n); + x.resize(len); + std::vector res(len); + std::uint32_t k = std::uint32_t(sqrt(x[0])); + assert(k != 0); + res[0] = std::min(P - k, k); + std::fill_n(a, len, 0); + a[0] = res[0].inv(); // a->h0 + b[0] = res[0], b[1] = ZERO; // b->g0 + dft(2, b); // b-> dft g0 + + for (i32 i = 2; i <= len; i <<= 1) { + for (i32 j = 0; j != i >> 1; ++j) + c[j] = b[j] * b[j]; + + idft(i >> 1, c); + + for (i32 j = 0; j != (i >> 1) - 1; ++j) + c[j + (i >> 1)] = c[j] - x[j] - x[j + (i >> 1)], c[j] = ZERO; + + c[(i >> 1) - 1] -= x[(i >> 1) - 1]; + c[i - 1] -= x[i - 1]; + std::copy_n(a, i, d); // d->h0 + dft(i, d), dft(i, c); + + for (i32 j = 0; j != i; ++j) + c[j] *= d[j]; + + idft(i, c); + + for (i32 j = i >> 1; j != i; ++j) + res[j] = -c[j] * iv2; + + std::copy_n(res.begin(), i, b); + dft(i, b); // b-> dft g0 + + for (i32 j = 0; j != i; ++j) + c[j] = b[j] * d[j]; + + idft(i, c); + std::fill_n(c, i >> 1, ZERO); + dft(i, c); + + for (i32 j = 0; j != i; ++j) + c[j] *= d[j]; + + idft(i, c); + + for (i32 j = i >> 1; j != i; ++j) + a[j] = -c[j]; + } + + return std::vector>(a, a + n); +} + +template +std::vector> pow(const std::vector> &x, +const MontgomeryModInt32

&k) { + std::vector> y(log(x)); + + for (auto &i : y) + i *= k; + + return exp(y); +} + +template +std::vector> operator+(const std::vector> &x, +const std::vector> &y) { + return add(x, y); +} + +template +std::vector> operator-(const std::vector> &x, +const std::vector> &y) { + return sub(x, y); +} + +template +std::vector> operator*(const std::vector> &x, +const std::vector> &y) { + return mul(x, y); +} + +template +std::vector> operator/(const std::vector> &x, +const std::vector> &y) { + return quorem(x, y); +} + +template +std::vector> operator%(const std::vector> &x, +const std::vector> &y) { + return rem(x, y); +} \ No newline at end of file diff --git "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12C - \345\244\232\351\241\271\345\274\217\357\274\210Poly, with. MInt\357\274\211.cpp" "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12D - \345\244\232\351\241\271\345\274\217\357\274\210Poly, with MInt\357\274\211.cpp" similarity index 96% rename from "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12C - \345\244\232\351\241\271\345\274\217\357\274\210Poly, with. MInt\357\274\211.cpp" rename to "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12D - \345\244\232\351\241\271\345\274\217\357\274\210Poly, with MInt\357\274\211.cpp" index 424e9e2..f2063c0 100644 --- "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12C - \345\244\232\351\241\271\345\274\217\357\274\210Poly, with. MInt\357\274\211.cpp" +++ "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/12D - \345\244\232\351\241\271\345\274\217\357\274\210Poly, with MInt\357\274\211.cpp" @@ -1,4 +1,4 @@ -/** 多项式(Poly, with. MInt & MLong) +/** 多项式(Poly, with MInt & MLong) * 2023-09-20: https://atcoder.jp/contests/arc163/submissions/45737810 * 2024-07-28: https://codeforces.com/contest/1991/submission/273204889 **/ diff --git "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/08 - \347\264\240\346\225\260\346\265\213\350\257\225\344\270\216\345\233\240\345\274\217\345\210\206\350\247\243\357\274\210Miller-Rabin & Pollard-Rho\357\274\211.cpp" "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/17 - \347\264\240\346\225\260\346\265\213\350\257\225\344\270\216\345\233\240\345\274\217\345\210\206\350\247\243\357\274\210Miller-Rabin & Pollard-Rho\357\274\211.cpp" similarity index 100% rename from "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/08 - \347\264\240\346\225\260\346\265\213\350\257\225\344\270\216\345\233\240\345\274\217\345\210\206\350\247\243\357\274\210Miller-Rabin & Pollard-Rho\357\274\211.cpp" rename to "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/03 - \346\225\260\350\256\272\343\200\201\345\207\240\344\275\225\344\270\216\345\244\232\351\241\271\345\274\217/17 - \347\264\240\346\225\260\346\265\213\350\257\225\344\270\216\345\233\240\345\274\217\345\210\206\350\247\243\357\274\210Miller-Rabin & Pollard-Rho\357\274\211.cpp" diff --git "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/11 - \351\253\230\347\262\276\345\272\246\357\274\210BigInt\357\274\211.cpp" "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/05 - \351\253\230\347\262\276\345\272\246\357\274\210BigInt\357\274\211.cpp" similarity index 100% rename from "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/11 - \351\253\230\347\262\276\345\272\246\357\274\210BigInt\357\274\211.cpp" rename to "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/05 - \351\253\230\347\262\276\345\272\246\357\274\210BigInt\357\274\211.cpp" diff --git "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/12 - Link-Cut Tree.md" "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/11 - Link-Cut Tree.md" similarity index 100% rename from "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/12 - Link-Cut Tree.md" rename to "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/04 - \346\225\260\346\215\256\347\273\223\346\236\204/11 - Link-Cut Tree.md" diff --git "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/05 - \345\255\227\347\254\246\344\270\262/03A - \345\220\216\347\274\200\346\225\260\347\273\204\357\274\210SuffixArray \346\227\247\347\211\210\357\274\211.cpp" "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/05 - \345\255\227\347\254\246\344\270\262/03A - \345\220\216\347\274\200\346\225\260\347\273\204\357\274\210SuffixArray\357\274\211.cpp" similarity index 58% rename from "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/05 - \345\255\227\347\254\246\344\270\262/03A - \345\220\216\347\274\200\346\225\260\347\273\204\357\274\210SuffixArray \346\227\247\347\211\210\357\274\211.cpp" rename to "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/05 - \345\255\227\347\254\246\344\270\262/03A - \345\220\216\347\274\200\346\225\260\347\273\204\357\274\210SuffixArray\357\274\211.cpp" index a8ce986..166dfe2 100644 --- "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/05 - \345\255\227\347\254\246\344\270\262/03A - \345\220\216\347\274\200\346\225\260\347\273\204\357\274\210SuffixArray \346\227\247\347\211\210\357\274\211.cpp" +++ "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/05 - \345\255\227\347\254\246\344\270\262/03A - \345\220\216\347\274\200\346\225\260\347\273\204\357\274\210SuffixArray\357\274\211.cpp" @@ -1,7 +1,8 @@ -/** 后缀数组(SuffixArray 旧版) +/** 后缀数组(SuffixArray) * 2023-03-14: https://atcoder.jp/contests/discovery2016-qual/submissions/39727257 * 2023-09-05: https://qoj.ac/submission/164483 * 2024-04-09: https://qoj.ac/submission/384415 【模板】 + * 2024-10-18: https://qoj.ac/submission/649558 **/ struct SuffixArray { int n; @@ -12,39 +13,50 @@ struct SuffixArray { lc.resize(n - 1); rk.resize(n); std::iota(sa.begin(), sa.end(), 0); - std::sort(sa.begin(), sa.end(), [&](int a, int b) {return s[a] < s[b];}); + std::sort(sa.begin(), sa.end(), + [&](int a, int b) { + return s[a] < s[b]; + }); rk[sa[0]] = 0; - for (int i = 1; i < n; ++i) + for (int i = 1; i < n; i++) { rk[sa[i]] = rk[sa[i - 1]] + (s[sa[i]] != s[sa[i - 1]]); + } int k = 1; std::vector tmp, cnt(n); tmp.reserve(n); while (rk[sa[n - 1]] < n - 1) { tmp.clear(); - for (int i = 0; i < k; ++i) + for (int i = 0; i < k; i++) { tmp.push_back(n - k + i); - for (auto i : sa) - if (i >= k) + } + for (auto i : sa) { + if (i >= k) { tmp.push_back(i - k); + } + } std::fill(cnt.begin(), cnt.end(), 0); - for (int i = 0; i < n; ++i) - ++cnt[rk[i]]; - for (int i = 1; i < n; ++i) + for (int i = 0; i < n; i++) { + cnt[rk[i]]++; + } + for (int i = 1; i < n; i++) { cnt[i] += cnt[i - 1]; - for (int i = n - 1; i >= 0; --i) + } + for (int i = n - 1; i >= 0; i--) { sa[--cnt[rk[tmp[i]]]] = tmp[i]; + } std::swap(rk, tmp); rk[sa[0]] = 0; - for (int i = 1; i < n; ++i) + for (int i = 1; i < n; i++) { rk[sa[i]] = rk[sa[i - 1]] + (tmp[sa[i - 1]] < tmp[sa[i]] || sa[i - 1] + k == n || tmp[sa[i - 1] + k] < tmp[sa[i] + k]); + } k *= 2; } - for (int i = 0, j = 0; i < n; ++i) { + for (int i = 0, j = 0; i < n; i++) { if (rk[i] == 0) { j = 0; } else { - for (j -= j > 0; i + j < n && sa[rk[i] - 1] + j < n && s[i + j] == s[sa[rk[i] - 1] + j]; ) - ++j; + for (j -= (j > 0); i + j < n && sa[rk[i] - 1] + j < n && s[i + j] == s[sa[rk[i] - 1] + j]; j++) + ; lc[rk[i] - 1] = j; } } diff --git "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/05 - \345\255\227\347\254\246\344\270\262/03B - \345\220\216\347\274\200\346\225\260\347\273\204\357\274\210SA\345\217\212\345\205\266\345\272\224\347\224\250 \346\226\260\347\211\210\357\274\211.cpp" "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/05 - \345\255\227\347\254\246\344\270\262/03B - \345\220\216\347\274\200\346\225\260\347\273\204\357\274\210SA\357\274\211.cpp" similarity index 95% rename from "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/05 - \345\255\227\347\254\246\344\270\262/03B - \345\220\216\347\274\200\346\225\260\347\273\204\357\274\210SA\345\217\212\345\205\266\345\272\224\347\224\250 \346\226\260\347\211\210\357\274\211.cpp" rename to "03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/05 - \345\255\227\347\254\246\344\270\262/03B - \345\220\216\347\274\200\346\225\260\347\273\204\357\274\210SA\357\274\211.cpp" index 23dda76..9b51a6d 100644 --- "a/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/05 - \345\255\227\347\254\246\344\270\262/03B - \345\220\216\347\274\200\346\225\260\347\273\204\357\274\210SA\345\217\212\345\205\266\345\272\224\347\224\250 \346\226\260\347\211\210\357\274\211.cpp" +++ "b/03 - jiangly\346\250\241\346\235\277\346\224\266\351\233\206/05 - \345\255\227\347\254\246\344\270\262/03B - \345\220\216\347\274\200\346\225\260\347\273\204\357\274\210SA\357\274\211.cpp" @@ -1,4 +1,4 @@ -/** 后缀数组(SA及其应用 新版) +/** 后缀数组(SA) * 2023-09-24: https://qoj.ac/submission/187270 * 2024-04-07: https://qoj.ac/submission/381482 **/