├── LC.cpp ├── README.md ├── TCS cheat sheet.pdf ├── Todo.txt ├── autoSave.sh ├── cp_template.pdf ├── default.cpp ├── single-page-integral-table.pdf ├── symbols.pdf ├── 图论.cpp ├── 多项式靶子.cpp ├── 字符串.cpp ├── 数学.cpp ├── 数据结构.cpp ├── 组合.cpp ├── 联合省选2022讲评.pdf └── 计算几何.cpp /LC.cpp: -------------------------------------------------------------------------------- 1 | // Skyqwq 2 | #define pb push_back 3 | #define fi first 4 | #define se second 5 | #define mp make_pair 6 | 7 | using namespace std; 8 | 9 | typedef pair PII; 10 | typedef long long LL; 11 | 12 | template bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } 13 | template bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a competitive programming template mainly used for ICPC competitions. Currently, it basically contains all mainstream knowledge points. 2 | 3 | I've been an amateur in competitive programming since 2019. My account can be found at [UOJ](https://uoj.ac/user/profile/moransky), [LOJ](https://loj.ac/u/MoRanSky), [QOJ](https://qoj.ac/user/profile/MoRanSky), [Codeforces](https://codeforces.com/profile/Skyqwq). [Codechef](https://www.codechef.com/users/moransky), [DMOJ](https://dmoj.ca/user/SkyCrystal), [Nowcoder](https://ac.nowcoder.com/acm/contest/profile/404610309), [Leetcode](https://leetcode.cn/u/moransky/), [Luogu](https://www.luogu.com.cn/user/161687), [Acwing](https://www.acwing.com/user/myspace/index/5751/). You can also access my Chinese blog [here](https://www.cnblogs.com/dmoransky/). 4 | 5 | The whole code can be viewed in dot cpp in different classifications. And the lite version of the pdf, which I think it will be used in the ICPC is "cp_template.pdf". 6 | 7 | If you have any questions, you can send the issue. 8 | 9 | -------------------------------------------------------------------------------- /TCS cheat sheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DMoRanSky/cp-template/bed339f13fd83ff3d917077ebd32a92c66dc6f3c/TCS cheat sheet.pdf -------------------------------------------------------------------------------- /Todo.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DMoRanSky/cp-template/bed339f13fd83ff3d917077ebd32a92c66dc6f3c/Todo.txt -------------------------------------------------------------------------------- /autoSave.sh: -------------------------------------------------------------------------------- 1 | cd /Users/xiangyufan/Documents/std/code/OI-template-main 2 | git add . 3 | git commit -m "SQD" 4 | git push origin master -------------------------------------------------------------------------------- /cp_template.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DMoRanSky/cp-template/bed339f13fd83ff3d917077ebd32a92c66dc6f3c/cp_template.pdf -------------------------------------------------------------------------------- /default.cpp: -------------------------------------------------------------------------------- 1 | // Skyqwq 2 | #include 3 | 4 | #define pb push_back 5 | #define fi first 6 | #define se second 7 | #define mp make_pair 8 | 9 | using namespace std; 10 | 11 | typedef pair PII; 12 | typedef long long LL; 13 | 14 | template bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } 15 | template bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } 16 | 17 | template void inline read(T &x) { 18 | int f = 1; x = 0; char s = getchar(); 19 | while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } 20 | while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); 21 | x *= f; 22 | } 23 | 24 | int main() { 25 | 26 | return 0; 27 | } -------------------------------------------------------------------------------- /single-page-integral-table.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DMoRanSky/cp-template/bed339f13fd83ff3d917077ebd32a92c66dc6f3c/single-page-integral-table.pdf -------------------------------------------------------------------------------- /symbols.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DMoRanSky/cp-template/bed339f13fd83ff3d917077ebd32a92c66dc6f3c/symbols.pdf -------------------------------------------------------------------------------- /图论.cpp: -------------------------------------------------------------------------------- 1 | int head[N], numE = 1; 2 | 3 | struct E{ 4 | int next, v, w; 5 | } e[M << 1]; 6 | 7 | void add(int u, int v, int w) { 8 | e[++numE] = (E) { head[u], v, w }; 9 | head[u] = numE; 10 | } 11 | 12 | // Dijkstra 13 | 14 | typedef pair PII; 15 | 16 | priority_queue, greater > q; 17 | 18 | void dijkstra() { 19 | memset(d, 0x3f, sizeof d); 20 | d[1] = 0; q.push(make_pair(0, 1)); 21 | while(!q.empty()) { 22 | PII u = q.top(); q.pop(); 23 | if(vis[u.se]) continue; 24 | vis[u.se] = true; 25 | for (int i = head[u.se]; i; i = e[i].next) { 26 | int v = e[i].v; 27 | if(d[u.se] + e[i].w < d[v]) { 28 | d[v] = d[u.se] + e[i].w; 29 | q.push(make_pair(d[v], v)); 30 | } 31 | } 32 | } 33 | } 34 | 35 | 36 | // Spfa 37 | 38 | // Prufer 39 | void inline fToP() { 40 | for (int i = 1; i < n; i++) d[f[i]]++; 41 | for (int i = 1, j = 1; i <= n - 2; j++) { 42 | while (d[j]) j++; 43 | p[i++] = f[j]; 44 | while (i <= n - 2 && --d[p[i - 1]] == 0 && p[i - 1] < j) p[i++] = f[p[i - 1]]; 45 | } 46 | } 47 | 48 | void inline pToF() { 49 | for (int i = 1; i <= n - 2; i++) d[p[i]]++; 50 | p[n - 1] = n; 51 | for (int i = 1, j = 1; i < n; i++, j++) { 52 | while (d[j]) j++; 53 | f[j] = p[i]; 54 | while (i < n - 1 && --d[p[i]] == 0 && p[i] < j) f[p[i]] = p[i + 1], ++i; 55 | } 56 | } 57 | 58 | // 有向图 tarjan 59 | 60 | void tarjan(int u) { 61 | dfn[u] = low[u] = ++dfncnt; 62 | s[++top] = u, ins[u] = true; 63 | for (int i = head[u]; i; i = e[i].next) { 64 | int v = e[i].v; 65 | if (!dfn[v]) { 66 | tarjan(v), low[u] = min(low[u], low[v]); 67 | } else if (ins[v]) low[u] = min(low[u], dfn[v]); 68 | } 69 | if (low[u] == dfn[u]) { 70 | int v; ++cnt; 71 | do { 72 | v = s[top--], ins[v] = false, col[v] = cnt; 73 | } while (v != u); 74 | } 75 | } 76 | 77 | // 最大流 78 | namespace MF{ 79 | int n, m, s, t, pre[N], cur[N], q[N]; 80 | LL res, maxflow, d[N]; 81 | int head[N], numE = 1; 82 | struct E{ 83 | int next, v, w; 84 | } e[M << 1]; 85 | 86 | void inline add(int u, int v, int w) { 87 | e[++numE] = (E) { head[u], v, w }; 88 | head[u] = numE; 89 | } 90 | void inline init(int v, int a, int b) { 91 | for (int i = 1; i <= n; i++) head[i] = 0; 92 | numE = 1; 93 | n = v, s = a, t = b; 94 | } 95 | 96 | bool inline bfs() { 97 | int hh = 0, tt = -1; 98 | for (int i = 1; i <= n; i++) d[i] = 0; 99 | q[++tt] = s, d[s] = 1, cur[s] = head[s]; 100 | while (hh <= tt) { 101 | int u = q[hh++]; 102 | for (int i = head[u]; i; i = e[i].next) { 103 | int v = e[i].v; 104 | if (!d[v] && e[i].w) { 105 | cur[v] = head[v]; 106 | q[++tt]= v, d[v] = d[u] + 1; 107 | if (v == t) return 1; 108 | } 109 | } 110 | } 111 | return 0; 112 | } 113 | LL dinic(int u, LL flow) { 114 | if (u == t) return flow; 115 | LL rest = flow; 116 | for (int i = cur[u]; i && rest; i = e[i].next) { 117 | cur[u] = i; 118 | int v = e[i].v; 119 | if (e[i].w&& d[v] == d[u] + 1) { 120 | int k = dinic(v, min((LL)e[i].w, rest)); 121 | if (!k) d[v] = 0; 122 | rest -= k, e[i].w -= k,e[i ^ 1].w += k; 123 | } 124 | } 125 | return flow - rest; 126 | } 127 | void inline addE(int u, int v, int w) { 128 | add(u, v, w), add(v, u, 0); 129 | } 130 | LL inline work() { 131 | maxflow = 0; 132 | while (bfs()) 133 | while (res = dinic(s, INF)) maxflow += res; 134 | return maxflow; 135 | } 136 | // Find min-cut 137 | bool vis[N]; 138 | 139 | void dfs(int u) { 140 | //cerr << u << " dfs\n"; 141 | vis[u] = 1; 142 | for (int i = head[u]; i; i = e[i].next) { 143 | int v = e[i].v; 144 | if (!vis[v] && e[i].w) dfs(v); 145 | } 146 | } 147 | 148 | void minCut() { 149 | for (int i = 1; i <= n; i++) vis[i] = 0; 150 | dfs(s); 151 | } 152 | } 153 | 154 | 155 | // ----重链剖分---- 156 | 157 | int sz[SZ], fa[SZ], dep[SZ], top[SZ], hson[SZ]; 158 | 159 | void dfs1(int u) { 160 | sz[u] = 1; 161 | for (int i = head[u]; i; i = e[i].next) { 162 | int v = e[i].v; 163 | if (v == fa[u]) continue; 164 | dep[v] = dep[u] + 1, fa[v] = u; 165 | dfs1(v); 166 | sz[u] += sz[v]; 167 | if (sz[v] > sz[hson[u]]) hson[u] = v; 168 | } 169 | } 170 | 171 | void dfs2(int u, int tp) { 172 | top[u] = tp; 173 | if (hson[u]) dfs2(hson[u], tp); 174 | for (int i = head[u]; i; i = e[i].next) { 175 | int v = e[i].v; 176 | if (v == fa[u] || v == hson[u]) continue; 177 | dfs2(v, v); 178 | } 179 | } 180 | 181 | int lca(int x, int y) { 182 | while (top[x] != top[y]) { 183 | if (dep[top[x]] < dep[top[y]]) swap(x, y); 184 | x = fa[top[x]]; 185 | } 186 | if (dep[x] < dep[y]) swap(x, y); 187 | return y; 188 | } 189 | 190 | 191 | // ---- End 重链剖分---- 192 | 193 | 194 | // Start :最小树形图 195 | 196 | int rt = 1, col, in[N]; 197 | 198 | int vis[N], id[N], pre[N]; 199 | 200 | struct E{ 201 | int u, v, w; 202 | } e[M]; 203 | 204 | int inline edmonds() { 205 | int ans = 0; 206 | while (true) { 207 | for (int i = 1; i <= n; i++) in[i] = INF; 208 | memset(vis, 0, sizeof vis); 209 | memset(id, 0, sizeof id); 210 | for (int i = 1; i <= m; i++) 211 | if (e[i].w < in[e[i].v]) in[e[i].v] = e[i].w, pre[e[i].v] = e[i].u; 212 | for (int i = 1; i <= n; i++) 213 | if (in[i] == INF && i != rt) return -1; 214 | col = 0; 215 | for (int i = 1; i <= n; i++) { 216 | if (i == rt) continue; 217 | ans += in[i]; 218 | int v = i; 219 | while (!vis[v] && !id[v] && v != rt) 220 | vis[v] = i, v = pre[v]; 221 | if (v != rt && vis[v] == i) { 222 | id[v] = ++col; 223 | for (int x = pre[v]; x != v; x = pre[x]) id[x] = col; 224 | } 225 | } 226 | if (!col) break; 227 | for (int i = 1; i <= n; i++) if (!id[i]) id[i] = ++col; 228 | int tot = 0; 229 | for (int i = 1; i <= m; i++) { 230 | int a = id[e[i].u], b = id[e[i].v]; 231 | if (a == b) continue; 232 | e[++tot] = (E) { a, b, e[i].w - in[e[i].v] }; 233 | } 234 | m = tot, n = col, rt = id[rt]; 235 | } 236 | return ans; 237 | } 238 | 239 | // -- End 240 | 241 | // Start : 长链剖分 + O(1) k 级祖先 242 | 243 | int d[N], dep[N]; 244 | int g[N], son[N], fa[N][L], top[N]; 245 | LL res; 246 | 247 | vector U[N], D[N]; 248 | 249 | 250 | void dfs1(int u) { 251 | dep[u] = d[u] = d[fa[u][0]] + 1; 252 | for (int i = 1; fa[u][i - 1]; i++) fa[u][i] = fa[fa[u][i - 1]][i - 1]; 253 | for (int i = head[u]; i; i = e[i].next) { 254 | int v = e[i].v; 255 | dfs1(v); 256 | if (dep[v] > dep[u]) dep[u] = dep[v], son[u] = v; 257 | } 258 | } 259 | 260 | void dfs2(int u, int tp) { 261 | top[u] = tp; 262 | if (u == tp) { 263 | for (int x = u, i = 0; i <= dep[u] - d[u]; i++) 264 | U[u].push_back(x), x = fa[x][0]; 265 | for (int x = u, i = 0; i <= dep[u] - d[u]; i++) 266 | D[u].push_back(x), x = son[x]; 267 | } 268 | if (son[u]) dfs2(son[u], tp); 269 | for (int i = head[u]; i; i = e[i].next) { 270 | int v = e[i].v; 271 | if (v != son[u]) dfs2(v, v); 272 | } 273 | } 274 | 275 | int inline query(int x, int k) { 276 | if (!k) return x; 277 | x = fa[x][g[k]], k -= (1 << g[k]) + d[x] - d[top[x]], x = top[x]; 278 | return k < 0 ? D[x][-k] : U[x][k]; 279 | } 280 | 281 | 282 | // --End 283 | 284 | // 最小费用最大流 EK 285 | 286 | 287 | 288 | const int N = ?, M = ?; 289 | 290 | const int INF = 0x3f3f3f3f; 291 | 292 | int n, m, s, t, maxflow, cost, d[N], incf[N], pre[N]; 293 | 294 | int q[N]; 295 | 296 | int head[N], numE = 1; 297 | 298 | bool vis[N]; 299 | 300 | struct E{ 301 | int next, v, w, c; 302 | } e[M]; 303 | 304 | void inline add(int u, int v, int w, int c) { 305 | e[++numE] = (E) { head[u], v, w, c }; 306 | head[u] = numE; 307 | } 308 | 309 | // Spfa || 310 | bool spfa() { 311 | memset(vis, false, sizeof vis); 312 | memset(d, 0x3f, sizeof d); 313 | int hh = 0, tt = 1; 314 | q[0] = s; d[s] = 0; incf[s] = 2e9; 315 | while (hh != tt) { 316 | int u = q[hh++]; vis[u] = false; 317 | if (hh == N) hh = 0; 318 | for (int i = head[u]; i; i = e[i].next) { 319 | int v = e[i].v; 320 | if (e[i].w && d[u] + e[i].c < d[v]) { 321 | d[v] = d[u] + e[i].c; 322 | pre[v] = i; 323 | incf[v] = min(incf[u], e[i].w); 324 | if (!vis[v]) { 325 | q[tt++] = v; 326 | vis[v] = true; 327 | if (tt == N) tt = 0; 328 | } 329 | } 330 | } 331 | } 332 | return d[t] != INF; 333 | } 334 | 335 | void update() { 336 | int x = t; 337 | while (x != s) { 338 | int i = pre[x]; 339 | e[i].w -= incf[t], e[i ^ 1].w += incf[t]; 340 | x = e[i ^ 1].v; 341 | } 342 | maxflow += incf[t]; 343 | cost += d[t] * incf[t]; 344 | } 345 | 346 | // --End 347 | 348 | // 匈牙利 349 | 350 | int match[N]; 351 | bool vis[N]; 352 | 353 | bool find(int u) { 354 | for (int i = head[u]; i; i = e[i].next) { 355 | int v = e[i].v; 356 | if (vis[v]) continue; 357 | vis[v] = true; 358 | if (!match[v] || find(match[v])) { 359 | match[v] = u; return true; 360 | } 361 | } 362 | return false; 363 | } 364 | 365 | // End 366 | 367 | // 点分治 / 树 368 | 369 | int val; 370 | 371 | void findRoot(int u, int last, int &rt) { 372 | sz[u] = 1; int s = 0; 373 | for (int i = head[u]; i; i = e[i].next) { 374 | int v = e[i].v; 375 | if (st[v] || v == last) continue; 376 | findRoot(v, u, rt); 377 | sz[u] += sz[v], s = max(s, sz[v]); 378 | } 379 | s = max(s, S - sz[u]); 380 | if (s < val) val = s, rt = u; 381 | } 382 | 383 | void solve(int u) { 384 | if (st[u]) return; 385 | val = INF, findRoot(u, 0, u), st[u] = true; 386 | for (int i = head[u], j = 0; i; i = e[i].next) { 387 | int v = e[i].v; 388 | if (st[v]) continue; 389 | // Do sth 390 | } 391 | for (int i = head[u]; i; i = e[i].next) S = sz[e[i].v], solve(e[i].v); 392 | } 393 | 394 | S = n, solve(1); 395 | 396 | // End 397 | 398 | namespace KM{ 399 | int n, va[N], vb[N], match[N], last[N]; 400 | LL a[N], b[N], upd[N], w[N][N]; 401 | bool dfs(int u, int fa) { 402 | va[u] = 1; 403 | for (int v = 1; v <= n; v++) { 404 | if (vb[v]) continue; 405 | if (a[u] + b[v] == w[u][v]) { 406 | vb[v] = 1, last[v] = fa; 407 | if (!match[v] || dfs(match[v], v)) { 408 | match[v] = u; return true; 409 | } 410 | } else if (a[u] + b[v] - w[u][v] < upd[v]) 411 | upd[v] = a[u] + b[v] - w[u][v], last[v] = fa; 412 | } 413 | return false; 414 | } 415 | void inline calc(int len, LL d[N][N]) { 416 | n = len; 417 | for (int i = 1; i <= n; i++) 418 | for (int j = 1; j <= n; j++) w[i][j] = d[i][j]; 419 | for (int i = 1; i <= n; i++) { 420 | a[i] = -1e18, b[i] = 0; 421 | for (int j = 1; j <= n; j++) 422 | a[i] = max(a[i], w[i][j]); 423 | } 424 | for (int i = 1; i <= n; i++) { 425 | memset(va, 0, sizeof va); 426 | memset(vb, 0, sizeof vb); 427 | memset(upd, 0x3f, sizeof upd); 428 | int st = 0; match[0] = i; 429 | while (match[st]) { 430 | LL delta = 1e18; 431 | if (dfs(match[st], st)) break; 432 | for (int j = 1; j <= n; j++) { 433 | if (!vb[j] && upd[j] < delta) 434 | delta = upd[j], st = j; 435 | } 436 | for (int j = 1; j <= n; j++) { 437 | if (va[j]) a[j] -= delta; 438 | if (vb[j]) b[j] += delta; 439 | else upd[j] -= delta; 440 | } 441 | vb[st] = true; 442 | } 443 | while (st) { 444 | match[st] = match[last[st]]; 445 | st = last[st]; 446 | } 447 | } 448 | } 449 | } 450 | 451 | // 保序回归 452 | class IR { 453 | public: 454 | int p, w[N], f[N], y[N], t[N], id[N], n, t1[N], t2[N]; 455 | vector g[N]; 456 | void inline add(int u, int v) { 457 | g[u].push_back(v); 458 | } 459 | LL inline power(int a, int b) { 460 | LL res = 1; 461 | while (b--) res *= a; 462 | return res; 463 | } 464 | // -w((mid + 1 - y) ^ p - (mid - y) ^ p) 465 | LL inline calc1(int i, int mid) { 466 | return -(w[i] * (power(mid + 1 - y[i], p) - power(mid - y[i], p))); 467 | } 468 | 469 | // -(w(mid-y)^p)' 470 | LL inline calc2(int i, int mid) { 471 | return 2 * (y[i] - mid) - 1; 472 | } 473 | 474 | void solve(int l, int r, int L, int R) { 475 | if (l > r) return; 476 | if (L == R) { 477 | for (int i = l; i <= r; i++) f[t[i]] = L; 478 | return; 479 | } 480 | mf.init(r - l + 3, r - l + 2, r - l + 3); 481 | for (int i = l; i <= r; i++) id[t[i]] = i - l + 1; 482 | int mid = (L + R) >> 1; 483 | for (int i = l; i <= r; i++) { 484 | int u = t[i], c = R - L == 1 ? calc2(u, L) : calc1(u, mid); 485 | if (c > 0) mf.addE(mf.s, id[u], c); 486 | else mf.addE(id[u], mf.t, -c); 487 | for (int j = 0; j < g[u].size(); j++) { 488 | int v = g[u][j]; 489 | if (id[v]) mf.addE(id[u], id[v], INF); 490 | } 491 | } 492 | for (int i = l; i <= r; i++) id[t[i]] = 0; 493 | mf.work(); 494 | if (R - L == 1) { 495 | for (int i = l; i <= r; i++) 496 | f[t[i]] = !mf.d[i - l + 1] ? L : R; 497 | return; 498 | } 499 | int c1 = 0, c2 = 0; 500 | for (int i = l; i <= r; i++) 501 | if (!mf.d[i - l + 1]) t1[++c1] = t[i]; 502 | else t2[++c2] = t[i]; 503 | for (int i = 1; i <= c1; i++) 504 | t[l + i - 1] = t1[i]; 505 | for (int i = 1; i <= c2; i++) 506 | t[l + c1 + i - 1] = t2[i]; 507 | solve(l, l + c1 - 1, L, mid); 508 | solve(l + c1, r, mid + 1, R); 509 | } 510 | 511 | LL inline work(int len, int P, int W[], int Y[]) { 512 | n = len, p = P; 513 | int mn = 2e9, mx = -2e9; 514 | for (int i = 1; i <= n; i++) 515 | t[i] = i, w[i] = W[i], y[i] = Y[i], mn = min(mn, y[i]), mx = max(mx, y[i]); 516 | solve(1, n, mn, mx); 517 | LL res = 0; 518 | for (int i = 1; i <= n; i++) 519 | res += power(f[i] - y[i], p); 520 | return res; 521 | } 522 | } ir; 523 | 524 | // 有负圈 / 上下界 525 | struct MCMF2{ 526 | 527 | const int N = 205, M = 10005; 528 | 529 | const int INF = 0x3f3f3f3f; 530 | 531 | int n, m, s, t, maxflow, cost, d[N], incf[N], pre[N]; 532 | int q[N], in, S, T; 533 | int head[N], a[N], numE = 1, a0, a1; 534 | bool vis[N]; 535 | struct E{ 536 | int next, v, w, c; 537 | } e[M << 2]; 538 | void inline add(int u, int v, int w, int c) { 539 | e[++numE] = (E) { head[u], v, w, c }; 540 | head[u] = numE; 541 | } 542 | void inline addE(int u, int v, int w, int c) { 543 | add(u, v, w, c), add(v, u, 0, -c); 544 | } 545 | bool spfa() { 546 | memset(vis, false, sizeof vis); 547 | memset(d, 0x3f, sizeof d); 548 | int hh = 0, tt = 1; 549 | q[0] = S; d[S] = 0; incf[S] = 2e9; 550 | while (hh != tt) { 551 | int u = q[hh++]; vis[u] = false; 552 | if (hh == N) hh = 0; 553 | for (int i = head[u]; i; i = e[i].next) { 554 | int v = e[i].v; 555 | if (e[i].w && d[u] + e[i].c < d[v]) { 556 | d[v] = d[u] + e[i].c; 557 | pre[v] = i; 558 | incf[v] = min(incf[u], e[i].w); 559 | if (!vis[v]) { 560 | q[tt++] = v; 561 | vis[v] = true; 562 | if (tt == N) tt = 0; 563 | } 564 | } 565 | } 566 | } 567 | return d[T] != INF; 568 | } 569 | void update() { 570 | int x = T; 571 | while (x != S) { 572 | int i = pre[x]; 573 | e[i].w -= incf[T], e[i ^ 1].w += incf[T]; 574 | x = e[i ^ 1].v; 575 | } 576 | maxflow += incf[T]; 577 | cost += d[T] * incf[T]; 578 | } 579 | 580 | void inline addEdge(int u, int v, int l, int d, int c) { 581 | a[v] += l, a[u] -= l; 582 | addE(u, v, d - l, c); 583 | } 584 | 585 | void inline work() { 586 | while (spfa()) update(); 587 | } 588 | 589 | void inline ADD(int u, int v, int w, int c) { 590 | if (c >= 0) addEdge(u, v, 0, w, c); 591 | else a[v] += w, a[u] -= w, addEdge(v, u, 0, w, -c), a1 += c * w; 592 | } 593 | 594 | void inline solve() { 595 | for (int i = 1; i <= n; i++) { 596 | if (!a[i]) continue; 597 | if (a[i] > 0) addEdge(S, i, 0, a[i], 0); 598 | else addEdge(i, T, 0, -a[i], 0); 599 | } 600 | addEdge(T, S, 0, INF, 0); 601 | work(); 602 | S = s, T = t; 603 | a1 += cost; 604 | maxflow = cost = 0; 605 | e[numE].w = e[numE - 1].w = 0; 606 | work(); 607 | a0 += maxflow, a1 += cost; 608 | } 609 | } 610 | 611 | // 虚树 612 | 613 | void insert(int x) { 614 | if (!top) { s[++top] = x; return; } 615 | int p = lca(x, s[top]); 616 | while (top > 1 && dep[s[top - 1]] >= dep[p]) e[s[top - 1]].pb(s[top]), top--; 617 | if (s[top] != p) { 618 | e[p].pb(s[top]); 619 | s[top] = p; 620 | } 621 | s[++top] = x; 622 | } 623 | 624 | 625 | bool inline cmp(int x, int y) { 626 | return dfn[x] < dfn[y]; 627 | } 628 | 629 | int inline build(vector &A) { 630 | top = 0; 631 | 632 | sort(A.begin(), A.end(), cmp); 633 | 634 | for (int x: A) { 635 | insert(x); 636 | } 637 | for (int i = 1; i < top; i++) 638 | e[s[i]].pb(s[i + 1]); 639 | return s[1]; 640 | } 641 | 642 | 643 | // 倍增 LCA 644 | 645 | 646 | int inline lca(int x, int y) { 647 | if (dep[x] < dep[y]) swap(x, y); 648 | for (int i = L - 1; ~i; i--) 649 | if (dep[x] - (1 << i) >= dep[y]) x = fa[x][i]; 650 | if (x == y) return x; 651 | for (int i = L - 1; ~i; i--) 652 | if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i]; 653 | return fa[x][0]; 654 | } 655 | 656 | // 圆方树 657 | 658 | int dfn[N], low[N], dfncnt, cnt; 659 | 660 | int s[N], top; 661 | 662 | void inline Add(int x, int y) { 663 | g[x].pb(y), g[y].pb(x); 664 | } 665 | 666 | void tarjan(int u, int fa) { 667 | dfn[u] = low[u] = ++dfncnt; 668 | s[++top] = u; 669 | for (int v: e[u]) { 670 | if (v == fa) continue; 671 | if (!dfn[v]) { 672 | tarjan(v, u); 673 | chkMin(low[u], low[v]); 674 | if (low[v] >= dfn[u]) { 675 | int y; ++cnt; 676 | do { 677 | y = s[top--], Add(y, cnt); 678 | } while (y != v); 679 | Add(cnt, u); 680 | } 681 | } else { 682 | chkMin(low[u], dfn[v]); 683 | } 684 | } 685 | } 686 | 687 | // 树上路径交 688 | 689 | // 从 $lca(u, x), lca(u, y), lca(v, x),lca(v, y)$ 四个点找深度最大的两个点,记为 $p_1, p_2$。 690 | 691 | // * 若 $p_1 = p_2$ 且 $dep_{p1} < \max(dep_{lca(x, y)}, dep_{lca(u, v)})$ 那么无相交路径 692 | // * 否则相交路径就是 $p_1$ 到 $p_2$ 693 | 694 | PII inline query(int u, int v, int x, int y) { 695 | int p[4] = { lca(u, x), lca(u, y), lca(v, x), lca(v, y)}; 696 | int w = lca(u, v), z = lca(x, y); 697 | int p1 = 0, p2 = 0; 698 | for (int i = 0; i < 4; i++) 699 | if (dep[p[i]] > dep[p1]) p2 = p1, p1 = p[i]; 700 | else if (dep[p[i]] > dep[p2]) p2 = p[i]; 701 | if (p1 == p2 && (dep[p1] < dep[w] || dep[p1] < dep[z])) return mp(-1, -1); 702 | // p1 - p2 是子路径 703 | return mp(p1, p2); 704 | } 705 | 706 | // O(1) LCA 707 | 708 | const int N = 5e5 + 5, L = 19; 709 | 710 | int n, m, dfncnt, rt, st[L][N], Lg[N], dfn[N], d[N], fa[N]; 711 | 712 | vector g[N]; 713 | 714 | void dfs0(int u) { 715 | st[0][dfncnt] = fa[u]; 716 | dfn[u] = ++dfncnt; 717 | for (int v: g[u]) { 718 | if (v == fa[u]) continue; 719 | d[v] = d[u] + 1; 720 | fa[v] = u; 721 | dfs0(v); 722 | } 723 | } 724 | 725 | int inline cmp(int x, int y) { 726 | return d[x] < d[y] ? x : y; 727 | } 728 | 729 | void inline bd() { 730 | Lg[0] = -1; 731 | for (int i = 1; i <= n; i++) 732 | Lg[i] = Lg[i >> 1] + 1; 733 | for (int j = 1; j <= Lg[n]; j++) 734 | for (int i = 1; i + (1 << j) - 1 <= n; i++) 735 | st[j][i] = cmp(st[j - 1][i], st[j - 1][i + (1 << (j - 1))]); 736 | } 737 | 738 | int inline lca(int x, int y) { 739 | if (x == y) return x; 740 | x = dfn[x], y = dfn[y]; 741 | if (x > y) swap(x, y); --y; 742 | int k = Lg[y - x + 1]; 743 | return cmp(st[k][x], st[k][y - (1 << k) + 1]); 744 | } 745 | 746 | void prework() { 747 | dfs0(rt); 748 | bd(); 749 | } 750 | 751 | // Use lca(a, b) 752 | 753 | // 上下界网络流 754 | 755 | struct NF{ 756 | int n, S, T, head[N], numE = 0, q[N], d[N], a[N], ans; 757 | 758 | struct E{ 759 | int next, v, w; 760 | } e[M]; 761 | 762 | void inline init(int len, int s, int t) { 763 | n = len, S = n + 1, T = n + 2, ans = 0; 764 | memset(head, 0, sizeof head); 765 | memset(a, 0, sizeof a); 766 | numE = 1; 767 | } 768 | 769 | void inline addEdge(int u, int v, int w) { 770 | e[++numE] = (E) { head[u], v, w }; 771 | head[u] = numE; 772 | } 773 | 774 | void inline add(int u, int v, int c, int d) { 775 | a[v] += c, a[u] -= c; 776 | addEdge(u, v, d - c), addEdge(v, u, 0); 777 | } 778 | 779 | bool inline bfs() { 780 | memset(d, 0, sizeof d); 781 | int hh = 0, tt = 0; q[0] = S; 782 | d[S] = 1; 783 | while (hh <= tt) { 784 | int u = q[hh++]; 785 | if (u == T) return true; 786 | for (int i = head[u]; i; i = e[i].next) { 787 | int v = e[i].v; 788 | if (e[i].w && !d[v]) { 789 | d[v] = d[u] + 1; 790 | q[++tt] = v; 791 | } 792 | } 793 | } 794 | return false; 795 | } 796 | 797 | int dinic(int u, int flow) { 798 | if (u == T) return flow; 799 | int rest = flow; 800 | for (int i = head[u]; i && rest; i = e[i].next) { 801 | int v = e[i].v; 802 | if (e[i].w && d[v] == d[u] + 1) { 803 | int k = dinic(v, min(rest, e[i].w)); 804 | if (!k) d[v] = 0; 805 | e[i].w -= k, e[i ^ 1].w += k, rest -= k; 806 | } 807 | } 808 | return flow - rest; 809 | } 810 | 811 | void inline prework() { 812 | for (int i = 1; i <= n; i++) 813 | if (a[i] > 0) addEdge(S, i, a[i]), addEdge(i, S, 0), ans += a[i]; 814 | else if (a[i] < 0) addEdge(i, T, -a[i]), addEdge(T, i, 0); 815 | } 816 | 817 | int inline run() { 818 | int res; 819 | addEdge(n, n - 1, INF); 820 | addEdge(n - 1, n, 0); 821 | while (bfs()) 822 | while(res = dinic(S, INF)) ans -= res; 823 | if (ans) return -1; 824 | ans = e[numE].w; 825 | e[numE].w = e[numE - 1].w = 0; 826 | S = n - 1, T = n; 827 | while (bfs()) 828 | while(res = dinic(S, INF)) ans += res; 829 | return ans; 830 | } 831 | 832 | } t; 833 | 834 | int S = n + m + 1, T = n + m + 2; 835 | t.init(T, S, T); 836 | t.add(u, v, c, d); 837 | t.prework(); 838 | output:: t.run() -------------------------------------------------------------------------------- /多项式靶子.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | typedef long long LL; 8 | typedef vector Poly; 9 | 10 | #define pb push_back 11 | 12 | const int N = 8e5 + 5, P = 998244353, G = 3; 13 | 14 | int A[N], rev[N], mod, inv[N], fact[N], infact[N]; 15 | int lim = 1, len = 0, W[20][N]; 16 | 17 | int inline power(int a, int b, int Mod = P) { 18 | int res = 1; 19 | while (b) { 20 | if (b & 1) res = (LL)res * a % Mod; 21 | a = (LL)a * a % Mod; 22 | b >>= 1; 23 | } 24 | return res; 25 | } 26 | 27 | 28 | namespace Red{ 29 | int MOD, I; 30 | 31 | struct Num{ 32 | int x, y; 33 | }; 34 | 35 | Num operator * (const Num a, const Num b) { 36 | return (Num) { (int)(((LL)a.x * b.x + (LL)I * a.y % P * b.y) % P) , (int)(((LL)a.x * b.y + (LL)a.y * b.x) % P) }; 37 | } 38 | 39 | int inline power(int a, int b, int Mod = P) { 40 | int res = 1; 41 | while (b) { 42 | if (b & 1) res = (LL)res * a % Mod; 43 | a = (LL)a * a % Mod; 44 | b >>= 1; 45 | } 46 | return res; 47 | } 48 | 49 | 50 | Num inline power(Num a, int b) { 51 | Num res = (Num) { 1, 0 }; 52 | while (b) { 53 | if (b & 1) res = res * a; 54 | a = a * a; 55 | b >>= 1; 56 | } 57 | return res; 58 | } 59 | 60 | int inline EulerCri(int x) { 61 | return power(x, (MOD - 1) >> 1, MOD); 62 | } 63 | 64 | int inline Sqrt(int n, int o) { 65 | MOD = o; 66 | if (n == 0) return 0; 67 | if (EulerCri(n) == P - 1) return -1; 68 | int a = rand() % P, t; 69 | while (EulerCri(t = ((LL)a * a + MOD - n) % P) != MOD - 1) a = rand() % MOD; 70 | I = t; 71 | int x0 = power((Num) { a, 1 }, (P + 1) >> 1).x; 72 | return min(x0, P - x0); 73 | } 74 | } 75 | 76 | int Gi = power(G, P - 2, P), inv2 = power(2, P - 2, P); 77 | 78 | 79 | /* 任意模数 80 | 81 | int MOD[3] = { 998244353, 1004535809, 469762049 }; 82 | 83 | int Inv1 = power(MOD[0], MOD[1] - 2, MOD[1]); 84 | int Inv2 = power((LL)MOD[0] * MOD[1] % MOD[2], MOD[2] - 2, MOD[2]); 85 | 86 | int inline get(int a, int b, int c) { 87 | LL x = ((LL)b - a + MOD[1]) % MOD[1] * Inv1 % MOD[1] * MOD[0] + a; 88 | return ((c - x % MOD[2] + MOD[2]) * Inv2 % MOD[2] * MOD[0] % mod * MOD[1] + x) % mod; 89 | } 90 | 91 | void reset(int o) { 92 | P = o; Gi = power(G, P - 2, P), inv2 = power(2, P - 2, P); 93 | } 94 | 95 | */ 96 | void inline NTT(int c[], int lim, int o) { 97 | for (int i = 0; i < lim; i++) 98 | if (i < rev[i]) swap(c[i], c[rev[i]]); 99 | for (int k = 1, t = 0; k < lim; k <<= 1, t++) { 100 | for (int i = 0; i < lim; i += (k << 1)) { 101 | for (int j = 0; j < k; j++) { 102 | int u = c[i + j], v = (LL)c[i + k + j] * W[t][j] % P; 103 | c[i + j] = u + v >= P ? u + v - P : u + v; 104 | c[i + j + k] = u - v < 0 ? u - v + P : u - v; 105 | } 106 | } 107 | } 108 | if (o == -1) { 109 | reverse(c + 1, c + lim); 110 | int inv = power(lim, P - 2, P); 111 | for (int i = 0; i < lim; i++) 112 | c[i] = (LL)c[i] * inv % P; 113 | } 114 | } 115 | 116 | void inline setN(int n) { 117 | lim = 1, len = 0; 118 | while (lim < n) lim <<= 1, len++; 119 | for (int i = 0; i < lim; i++) 120 | rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (len - 1)); 121 | } 122 | 123 | Poly inline NTT(Poly a, int o) { 124 | int n = a.size(); 125 | for (int i = 0; i < n; i++) A[i] = a[i]; 126 | NTT(A, lim, o); 127 | a.clear(); 128 | for (int i = 0; i < lim; i++) a.push_back(A[i]), A[i] = 0; 129 | return a; 130 | } 131 | 132 | Poly operator + (const Poly a, const Poly b) { 133 | Poly c(max(a.size(), b.size())); 134 | for (int i = 0; i < c.size(); i++) { 135 | if (i < a.size()) { 136 | c[i] += a[i]; if (c[i] >= P) c[i] -= P; 137 | } 138 | if (i < b.size()) { 139 | c[i] += b[i]; if (c[i] >= P) c[i] -= P; 140 | } 141 | } 142 | return c; 143 | } 144 | 145 | 146 | Poly operator - (const Poly a, const Poly b) { 147 | Poly c(max(a.size(), b.size())); 148 | for (int i = 0; i < c.size(); i++) { 149 | if (i < a.size()) { 150 | c[i] += a[i]; if (c[i] >= P) c[i] -= P; 151 | } 152 | if (i < b.size()) { 153 | c[i] -= b[i]; if (c[i] < 0) c[i] += P; 154 | } 155 | } 156 | return c; 157 | } 158 | 159 | Poly inline mul (Poly a, Poly b, int newn = -1) { 160 | if (newn == -1) newn = a.size() + b.size() - 1; 161 | setN(a.size() + b.size() - 1); 162 | Poly c = NTT(a, 1), d = NTT(b, 1); 163 | for (int i = 0; i < lim; i++) c[i] = (LL)c[i] * d[i] % P; 164 | d = NTT(c, -1); d.resize(newn); 165 | return d; 166 | } 167 | 168 | Poly inline reverse(Poly a) { 169 | int n = a.size() - 1; 170 | for (int i = 0; i < n - i; i++) swap(a[i], a[n - i]); 171 | return a; 172 | } 173 | 174 | Poly inline dx(Poly a) { 175 | int n = a.size(); 176 | Poly b; b.resize(n - 1); 177 | for (int i = 0; i < b.size(); i++) b[i] = a[i + 1] * (i + 1ll) % P; 178 | return b; 179 | } 180 | 181 | Poly inline F(Poly a) { 182 | int n = a.size(); 183 | Poly b; b.resize(n + 1); 184 | for (int i = 1; i < b.size(); i++) b[i] = (LL)a[i - 1] * inv[i] % P; 185 | return b; 186 | } 187 | 188 | Poly polyInv(Poly a) { 189 | int n = a.size(); 190 | if (n == 1) { Poly b; b.push_back(power(a[0], P - 2, P)); return b;} 191 | Poly b = a; b.resize((n + 1) >> 1); 192 | b = polyInv(b); 193 | setN(2 * n); 194 | a = NTT(a, 1), b = NTT(b, 1); 195 | for (int i = 0; i < lim; i++) 196 | b[i] = (LL)b[i] * (2ll - (LL)a[i] * b[i] % P + P) % P; 197 | b = NTT(b, -1); 198 | b.resize(n); 199 | return b; 200 | } 201 | 202 | // 注意必须保证 n >= m 203 | void inline div (Poly a, Poly b, Poly &Q, Poly &R) { 204 | int n = a.size() - 1, m = b.size() - 1; 205 | Poly ar = reverse(a), br = reverse(b); 206 | ar.resize(n - m + 1), br.resize(n - m + 1); 207 | Q = reverse(mul(ar, polyInv(br), n - m + 1)); 208 | R = a - mul(b, Q); R.resize(m); 209 | } 210 | 211 | 212 | Poly t(1, 1); 213 | 214 | Poly sqrt(Poly a) { 215 | int n = a.size(); 216 | if (n == 1) { Poly k; k.resize(1); k[0] = Red::Sqrt(a[0], P); return k; } 217 | Poly b = a; b.resize((n + 1) >> 1); 218 | b = sqrt(b), b.resize(n); 219 | Poly c = polyInv(b); 220 | setN(2 * n); 221 | b = NTT(b, 1), c = NTT(c, 1), a = NTT(a, 1); 222 | for (int i = 0; i < lim; i++) 223 | b[i] = (LL)inv2 * (b[i] + (LL)a[i] * c[i] % P) % P; 224 | b = NTT(b, -1); b.resize(n); 225 | return b; 226 | } 227 | 228 | Poly inline ln(Poly a) { 229 | Poly b = F(mul(dx(a), polyInv(a))); 230 | b.resize(a.size()); 231 | return b; 232 | } 233 | 234 | Poly exp(Poly a) { 235 | int n = a.size(); 236 | if (n == 1) return t; 237 | Poly b = a; b.resize((n + 1) >> 1); 238 | b = exp(b); b.resize(n); 239 | Poly c = a - ln(b); 240 | (c[0] += 1) %= P; 241 | b = mul(b, c, a.size()); 242 | return b; 243 | } 244 | 245 | void cdq(int l, int r) { 246 | if (r - l <= 0) return; 247 | int mid = (l + r) >> 1, len = r - l; 248 | cdq(l, mid); 249 | // Do sth 250 | cdq(mid + 1, r); 251 | } 252 | 253 | void inline preInv(int n) { 254 | inv[1] = 1; 255 | for (int i = 2; i <= n; i++) 256 | inv[i] = ((LL)P - P / i) * inv[P % i] % P; 257 | } 258 | 259 | 260 | bool ok = false; 261 | 262 | Poly inline power(Poly a, int b) { 263 | int Mul = 1, Cy = 0, n = a.size(); 264 | if (b == 0) { 265 | Poly c(n, 0); 266 | c[0] = power(a[0], b, P); 267 | return c; 268 | } 269 | if (a[0] == 0) { 270 | for (Cy = 1; Cy < n; Cy++) if (a[Cy]) break; 271 | if (ok || (LL)Cy * b >= n) { 272 | Poly c(n, 0); 273 | return c; 274 | } 275 | for (int i = 0; i + Cy < n; i++) a[i] = a[i + Cy]; 276 | for (int i = n - Cy; i < n; i++) a[i] = 0; 277 | Cy *= b; 278 | } 279 | if (a[0] != 1) { 280 | int in = power(a[0], P - 2, P); Mul = power(a[0], b, P); 281 | for (int i = 0; i < n; i++) a[i] = (LL)a[i] * in % P; 282 | } 283 | a = ln(a); 284 | for (int i = 0; i < n; i++) a[i] = (LL)a[i] * b % P; 285 | a = exp(a); 286 | if (Mul != 1) for (int i = 0; i < n; i++) a[i] = (LL)a[i] * Mul % P; 287 | if (Cy) { 288 | for (int i = n - 1; i >= Cy; i--) a[i] = a[i - Cy]; 289 | for (int i = 0; i < Cy; i++) a[i] = 0; 290 | } 291 | return a; 292 | } 293 | 294 | void inline factPrework(int n) { 295 | fact[0] = infact[0] = 1; 296 | for (int i = 1; i <= n; i++) fact[i] = (LL)fact[i - 1] * i % P; 297 | infact[n] = power(fact[n], P - 2); 298 | for (int i = n - 1; i; i--) infact[i] = infact[i + 1] * (i + 1ll) % P; 299 | } 300 | 301 | 302 | // 用到的最大的 n 303 | void inline init(int n) { 304 | preInv(n); 305 | factPrework(n); 306 | setN(2 * n); 307 | for (int k = 1, t = 0; k < lim; k <<= 1, t++) { 308 | int wn = power(G, (P - 1) / (k << 1)); 309 | W[t][0] = 1; 310 | for (int j = 1; j < k; j++) W[t][j] = (LL)W[t][j - 1] * wn % P; 311 | } 312 | } 313 | 314 | // 多点求值 315 | 316 | int bx[N], by[N]; 317 | 318 | Poly b[N]; 319 | 320 | void MpeBuild(int p, int l, int r) { 321 | if (l == r) { b[p].resize(2); b[p][0] = P - bx[r], b[p][1] = 1; return; } 322 | int mid = (l + r) >> 1; 323 | MpeBuild(p << 1, l, mid); 324 | MpeBuild(p << 1 | 1, mid + 1, r); 325 | b[p] = mul(b[p << 1], b[p << 1 | 1]); 326 | } 327 | 328 | void MpeSolve(int p, int l, int r, Poly a) { 329 | Poly Q, R; 330 | if (a.size() >= b[p].size()) div(a, b[p], Q, R), a = R; 331 | if (l == r) { by[r] = a[0]; return; } 332 | int mid = (l + r) >> 1; 333 | MpeSolve(p << 1, l, mid, a); 334 | MpeSolve(p << 1 | 1, mid + 1, r, a); 335 | } 336 | 337 | void MpeEva(int n, int m, Poly f, int X[], int Y[]) { 338 | for (int i = 1; i <= m; i++) bx[i] = X[i]; 339 | MpeBuild(1, 1, m); 340 | MpeSolve(1, 1, m, f); 341 | for (int i = 1; i <= m; i++) Y[i] = by[i]; 342 | } 343 | 344 | // 快速插值 345 | 346 | Poly bc[N]; 347 | 348 | void InterSolve(int p, int l, int r) { 349 | if (l == r) { bc[p].resize(1); bc[p][0] = by[r]; return; } 350 | int mid = (l + r) >> 1; 351 | InterSolve(p << 1, l, mid); 352 | InterSolve(p << 1 | 1, mid + 1, r); 353 | bc[p] = mul(bc[p << 1], b[p << 1 | 1]) + mul(bc[p << 1 | 1], b[p << 1]); 354 | } 355 | 356 | Poly polyInterpo(int n, int X[], int Y[]) { 357 | for (int i = 1; i <= n; i++) bx[i] = X[i]; 358 | MpeBuild(1, 1, n); 359 | Poly f = dx(b[1]); 360 | MpeSolve(1, 1, n, f); 361 | for (int i = 1; i <= n; i++) by[i] = (LL)Y[i] * power(by[i], P - 2) % P; 362 | InterSolve(1, 1, n); 363 | return bc[1]; 364 | } 365 | 366 | // f[0 ... n] 线性递推第 b 项 367 | // g[1 ~ k] 为递推多项式 368 | 369 | int inline LRS(int b, Poly f, Poly g) { 370 | int k = g.size() - 1; 371 | g[0] = 1; 372 | for (int i = 1; i <= k; i++) g[i] = (P - g[i]) % P; 373 | Poly h = mul(f, g, k); 374 | while (b) { 375 | Poly g2 = g; 376 | for (int i = 0; i < g2.size(); i += 2) 377 | g2[i] = (P - g2[i]) % P; 378 | Poly t = mul(g2, g); g.clear(); 379 | for (int i = 0; i < t.size(); i += 2) 380 | g.pb(t[i]); 381 | t = mul(g2, h); h.clear(); 382 | for (int i = (b & 1); i < t.size(); i += 2) 383 | h.pb(t[i]); 384 | b >>= 1; 385 | } 386 | return (LL)h[0] * power(g[0], P - 2) % P; 387 | } 388 | 389 | // _End_ 390 | 391 | 392 | int main() { 393 | 394 | return 0; 395 | } -------------------------------------------------------------------------------- /字符串.cpp: -------------------------------------------------------------------------------- 1 | // 中间添加 # 2 | char s[N], g[N]; 3 | 4 | void change() { 5 | n = strlen(s + 1) * 2; 6 | g[0] = 0; 7 | for (int i = 1; i <= n; i++) { 8 | if (i % 2) g[i] = 1; 9 | else g[i] = s[i >> 1]; 10 | } 11 | g[++n] = 1, g[n + 1] = 2; 12 | manacher(); 13 | } 14 | 15 | void manacher() { 16 | int r = 0, mid = 0; 17 | for (int i = 1; i <= n; i++) { 18 | p[i] = i <= r ? min(r - i + 1, p[2 * mid - i]) : 1; 19 | while (g[i - p[i]] == g[i + p[i]]) ++p[i]; 20 | if (i + p[i] - 1 > r) mid = i, r = i + p[i] - 1; 21 | ans = max(ans, p[i] - 1); 22 | } 23 | } 24 | 25 | struct KMP{ 26 | int n, nxt[SZ]; 27 | void inline build(char s[]) { 28 | n = strlen(s + 1); 29 | nxt[1] = 0; 30 | for (int i = 2, j = 0; i <= n; i++) { 31 | while (j && s[j + 1] != s[i]) j = nxt[j]; 32 | if (s[j + 1] == s[i]) j++; 33 | nxt[i] = j; 34 | } 35 | } 36 | void inline match(char a[], int m) { 37 | for (int i = 1, j = 0; i <= m; i++) { 38 | while (j && s[j + 1] != a[i]) j = nxt[j]; 39 | if (s[j + 1] == a[i]) j++; 40 | if (j == n) { 41 | j = nxt[j]; 42 | } 43 | } 44 | } 45 | } kmp; 46 | 47 | struct SA{ 48 | int rk[SZ], sa[SZ], cnt[SZ], oldrk[SZ], id[SZ], n, m, p, height[SZ]; 49 | bool inline cmp(int i, int j, int k) { 50 | return oldrk[i] == oldrk[j] && oldrk[i + k] == oldrk[j + k]; 51 | } 52 | void inline build(char s[]) { 53 | n = strlen(s + 1), m = 221; 54 | for (int i = 1; i <= n; i++) cnt[rk[i] = s[i]]++; 55 | for (int i = 1; i <= m; i++) cnt[i] += cnt[i - 1]; 56 | for (int i = n; i; i--) sa[cnt[rk[i]]--] = i; 57 | for (int w = 1; w < n; w <<= 1, m = p) { 58 | p = 0; 59 | for (int i = n; i > n - w; i--) id[++p] = i; 60 | for (int i = 1; i <= n; i++) 61 | if (sa[i] > w) id[++p] = sa[i] - w; 62 | for (int i = 1; i <= m; i++) cnt[i] = 0; 63 | for (int i = 1; i <= n; i++) cnt[rk[i]]++, oldrk[i] = rk[i]; 64 | for (int i = 1; i <= m; i++) cnt[i] += cnt[i - 1]; 65 | for (int i = n; i; i--) sa[cnt[rk[id[i]]]--] = id[i]; 66 | p = 0; 67 | for (int i = 1; i <= n; i++) { 68 | rk[sa[i]] = cmp(sa[i], sa[i - 1], w) ? p : ++p; 69 | } 70 | if (p == n) break; 71 | } 72 | for (int i = 1; i <= n; i++) { 73 | int j = sa[rk[i] - 1], k = max(0, height[rk[i - 1]] - 1); 74 | while (s[i + k] == s[j + k]) k++; 75 | height[rk[i]] = k; 76 | } 77 | } 78 | }; 79 | 80 | // 切记复制一倍到后面, 最小表示法,返回开始下标 81 | int inline minExp(int a[], int n) { 82 | int i = 1, j = 2; 83 | while (i <= n && j <= n) { 84 | int k; 85 | for (k = 0; k < n && a[i + k] == a[j + k]; k++); 86 | if (k == n) break; 87 | if (a[i + k] < a[j + k]) j += k + 1; 88 | else i += k + 1; 89 | if (i == j) i++; 90 | } 91 | return min(i, j); 92 | } 93 | 94 | typedef unsigned long long ULL; 95 | 96 | // 哈希 97 | 98 | struct Hash{ 99 | int b, P, p[N], h[N]; 100 | int inline get(int l, int r){ 101 | return (h[r] - (LL)h[l - 1] * p[r - l + 1] % P + P) % P; 102 | } 103 | void inline build(int n, int tb, int tp) { 104 | b = tb, P = tp; 105 | p[0] = 1; 106 | for(int i = 1; i <= n; i++){ 107 | p[i] = (LL)p[i - 1] * b % P; 108 | h[i] = ((LL)h[i - 1] * b + s[i]) % P; 109 | } 110 | } 111 | } 112 | 113 | // Z 函数 114 | 115 | z[1] = n; 116 | for (int i = 2, r = 0, j = 0; i <= n; i++) { 117 | if (i <= r) z[i] = min(r - i + 1, z[i - j + 1]); 118 | while (i + z[i] <= n && a[i + z[i]] == a[1 + z[i]]) z[i]++; 119 | if (i + z[i] - 1 > r) r = i + z[i] - 1, j = i; 120 | } 121 | 122 | for (int i = 1, r = 0, j = 0; i <= m; i++) { 123 | if (i <= r) p[i] = min(r - i + 1, z[i - j + 1]); 124 | while (i + p[i] <= m && b[i + p[i]] == a[1 + p[i]]) p[i]++; 125 | if (i + p[i] - 1 > r) r = i + p[i] - 1, j = i; 126 | } 127 | 128 | // End 129 | 130 | // AC 自动机 131 | 132 | struct ACAutomation{ 133 | int tr[SZ][26], nxt[SZ], idx, q[SZ]; 134 | void inline insert(char s[]) { 135 | int p = 0; 136 | for (int j = 0; s[j]; j++) { 137 | int ch = s[j] - 'a'; 138 | if(!tr[p][ch]) tr[p][ch] = ++idx; 139 | p = tr[p][ch]; 140 | } 141 | } 142 | void build() { 143 | int hh = 0, tt = -1; 144 | for (int i = 0; i < 26; i++) 145 | if (tr[0][i]) q[++tt] = tr[0][i]; 146 | while (hh <= tt) { 147 | int u = q[hh++]; 148 | for (int i = 0; i < 26; i++) { 149 | int v = tr[u][i]; 150 | if (!v) tr[u][i] = tr[nxt[u]][i]; 151 | else nxt[v] = tr[nxt[u]][i], q[++tt] = v; 152 | } 153 | } 154 | } 155 | } 156 | 157 | // Runs 158 | 159 | struct Runs{ 160 | typedef unsigned long long ULL; 161 | 162 | const int N = 1e6 + 5; 163 | 164 | int n, tot, b1[N], b2[N]; 165 | 166 | ULL H[N], P[N], B = 31; 167 | 168 | char s[N]; 169 | 170 | struct Node { 171 | int a, b, c; 172 | bool operator < (const Node &y) const { 173 | if (a != y.a) return a < y.a; 174 | if (b != y.b) return b < y.b; 175 | return c < y.c; 176 | } 177 | bool operator == (const Node &y) const { 178 | return a == y.a && b == y.b && c == y.c; 179 | } 180 | } ans[N << 1]; 181 | 182 | ULL inline get(int l, int r) { 183 | return H[r] - H[l - 1] * P[r - l + 1]; 184 | } 185 | 186 | int inline lcp(int i, int j) { 187 | if (s[i] != s[j]) return 0; 188 | int l = 1, r = min(n - i + 1, n - j + 1); 189 | while (l < r) { 190 | int mid = (l + r + 1) >> 1; 191 | if (get(i, i + mid - 1) == get(j, j + mid - 1)) l = mid; 192 | else r = mid - 1; 193 | } 194 | return r; 195 | } 196 | 197 | int inline lcs(int i, int j) { 198 | if (s[i] != s[j]) return 0; 199 | int l = 1, r = min(i, j); 200 | while (l < r) { 201 | int mid = (l + r + 1) >> 1; 202 | if (get(i - mid + 1, i) == get(j - mid + 1, j)) l = mid; 203 | else r = mid - 1; 204 | } 205 | return r; 206 | } 207 | 208 | int inline cmp(int i, int j) { 209 | int k = lcp(i, j); 210 | return s[i + k] < s[j + k]; 211 | } 212 | 213 | int inline cmp2(int i, int j) { 214 | int k = lcp(i, j); 215 | if (i + k == n + 1) return false; 216 | return s[i + k] < s[j + k]; 217 | } 218 | 219 | 220 | void inline add(int i, int j) { 221 | int L = lcs(i - 1, j), len = j - i + 1; 222 | if (true) { 223 | int R = lcp(i, j + 1); 224 | if (L + R >= len) ans[++tot] = (Node) { i - L, j + R, len }; 225 | } 226 | } 227 | 228 | void inline prework() { 229 | P[0] = 1; 230 | for (int i = 1; i <= n; i++) { 231 | P[i] = P[i - 1] * B; 232 | H[i] = (H[i - 1] * B + s[i] - 'a'); 233 | } 234 | } 235 | 236 | void inline Runs() { 237 | for (int i = n; i; i--) { 238 | b1[i] = b2[i] = i + 1; 239 | while (b1[i] < n && cmp(i, b1[i])) b1[i] = b1[b1[i]]; 240 | while (b2[i] < n && cmp2(b2[i], i)) b2[i] = b2[b2[i]]; 241 | add(i, b1[i] - 1); 242 | if (b1[i] != b2[i]) add(i, b2[i] - 1); 243 | } 244 | sort(ans + 1, ans + 1 + tot); 245 | tot = unique(ans + 1, ans + 1 + tot) - ans - 1; 246 | } 247 | 248 | } 249 | 250 | struct SAM{ 251 | int idx, last; 252 | struct SAM_{ 253 | int nxt[26], len, link; 254 | } t[N]; 255 | void inline init() { 256 | last = idx = 1; 257 | } 258 | 259 | void inline extend(int c) { 260 | int x = ++idx, p = last; sz[x] = 1; 261 | t[x].len = t[last].len + 1; 262 | while (p && !t[p].nxt[c]) 263 | t[p].nxt[c] = x, p = t[p].link; 264 | if (!p) t[x].link = 1; 265 | else { 266 | int q = t[p].nxt[c]; 267 | if (t[p].len + 1 == t[q].len) t[x].link = q; 268 | else { 269 | int y = ++idx; 270 | t[y] = t[q], t[y].len = t[p].len + 1; 271 | while (p && t[p].nxt[c] == q) 272 | t[p].nxt[c] = y, p = t[p].link; 273 | t[q].link = t[x].link = y; 274 | } 275 | } 276 | last = x; 277 | } 278 | } t; 279 | 280 | struct GSAM{ 281 | int idx, last; 282 | struct SAM{ 283 | int ch[26], len, link; 284 | } t[N]; 285 | void inline init() { 286 | last = idx = 1; 287 | } 288 | void inline insert(int c) { 289 | int p = last; 290 | if (t[p].ch[c]) { 291 | int q = t[p].ch[c]; 292 | if (t[q].len == t[p].len + 1) last = q; 293 | else { 294 | int y = ++idx; t[y] = t[q]; 295 | t[y].len = t[p].len + 1; 296 | while (p && t[p].ch[c] == q) 297 | t[p].ch[c] = y, p = t[p].link; 298 | t[q].link = y; 299 | last = y; 300 | } 301 | return; 302 | } 303 | int x = ++idx; t[x].len = t[p].len + 1; 304 | while (p && !t[p].ch[c]) t[p].ch[c] = x, p = t[p].link; 305 | int q, y; 306 | if (!p) t[x].link = 1; 307 | else { 308 | q = t[p].ch[c]; 309 | if (t[q].len == t[p].len + 1) t[x].link = q; 310 | else { 311 | int y = ++idx; t[y] = t[q]; 312 | t[y].len = t[p].len + 1; 313 | while (p && t[p].ch[c] == q) 314 | t[p].ch[c] = y, p = t[p].link; 315 | t[q].link = t[x].link = y; 316 | last = y; 317 | } 318 | } 319 | last = x; 320 | } 321 | } t; 322 | 323 | // 回文自动机 324 | struct PAM{ 325 | int n, ch[N][26], fail[N], len[N], sz[N], idx = -1, last; 326 | char s[N]; 327 | void clr() { 328 | n = 0; 329 | for (int i = 0; i <= idx; i++) { 330 | sz[i] = len[i] = fail[i] = 0; 331 | for (int j = 0; j < 26; j++) 332 | ch[i][j] = 0; 333 | } 334 | idx = -1; 335 | last = 0; 336 | } 337 | 338 | int newNode(int x) { len[++idx] = x; return idx; } 339 | int getFail(int x) { 340 | while (s[n - len[x] - 1] != s[n]) x = fail[x]; 341 | return x; 342 | } 343 | int insert(char c) { 344 | int k = c - 'a'; 345 | s[++n] = c; 346 | int p = getFail(last), x; 347 | if (!ch[p][k]) { 348 | x = newNode(len[p] + 2); 349 | fail[x] = ch[getFail(fail[p])][k]; 350 | ch[p][k] = x, sz[x] = 1 + sz[fail[x]]; 351 | } else x = ch[p][k]; 352 | last = x; 353 | return x; 354 | } 355 | void bd() { 356 | // -1:idx jigen 357 | newNode(0), newNode(-1); 358 | s[0] = '$', fail[0] = 1, last = 0; 359 | } 360 | } pam; 361 | 362 | -------------------------------------------------------------------------------- /数学.cpp: -------------------------------------------------------------------------------- 1 | // 扩域 2 | struct C{ 3 | int x, y; 4 | // x + y * sqrt(o); 5 | }; 6 | 7 | int o = 2; 8 | 9 | // fn = Aa^n + Bb^n 10 | 11 | int inline power(int a, int b) { 12 | int ret = 1; 13 | while (b) { 14 | if (b & 1) ret = 1ll * ret * a % P; 15 | a = 1ll * a * a % P; 16 | b >>= 1; 17 | } 18 | return ret; 19 | } 20 | 21 | 22 | 23 | 24 | int mod(int x) { 25 | return x >= P ? x - P : x; 26 | } 27 | 28 | C operator + (const C &a, const C &b) { 29 | return (C) { mod(a.x + b.x), mod(a.y + b.y) }; 30 | }; 31 | 32 | C operator * (const C &a, const C &b) { 33 | C c; 34 | c.x = (1ll * a.x * b.x + 1ll * a.y * b.y % P * o) % P; 35 | c.y = (1ll * a.x * b.y + 1ll * a.y * b.x) % P; 36 | return c; 37 | }; 38 | 39 | C operator * (const C &a, const int &b) { 40 | C c; 41 | c.x = 1ll * a.x * b % P; 42 | c.y = 1ll * a.y * b % P; 43 | 44 | return c; 45 | }; 46 | 47 | 48 | C inline power(C a, int b) { 49 | C ret = (C) { 1, 0 } ; 50 | while (b) { 51 | if (b & 1) ret = ret * a; 52 | a = a * a; 53 | b >>= 1; 54 | } 55 | return ret; 56 | } 57 | 58 | C operator / (const C &a, const C &b) { 59 | C c, d; 60 | c = a; 61 | d = b; 62 | d.y = mod(P - d.y); 63 | c = c * d; 64 | int I = (((LL)b.x * b.x - (LL)b.y * b.y * o) % P + P) % P; 65 | I = power(I, P - 2); 66 | c = c * I; 67 | return c; 68 | }; 69 | 70 | // 原根 / 封装不太好 71 | 72 | 73 | int n, D, phi[N], primes[N], tot, d[N], len; 74 | int ans[N], cnt; 75 | 76 | bool st[N], pr[N]; 77 | 78 | void inline init() { 79 | phi[1] = 1, pr[2] = pr[4] = true; 80 | for (int i = 2; i < N; i++) { 81 | if (!st[i]) primes[tot++] = i, phi[i] = i - 1; 82 | for (int j = 0; i * primes[j] < N; j++) { 83 | st[i * primes[j]] = true; 84 | if (i % primes[j] == 0) { 85 | phi[i * primes[j]] = phi[i] * primes[j]; 86 | break; 87 | } 88 | phi[i * primes[j]] = phi[i] * (primes[j] - 1); 89 | } 90 | } 91 | for (int i = 1; i < tot; i++) { 92 | for (LL j = primes[i]; j < N; j *= primes[i]) pr[j] = true; 93 | for (LL j = 2 * primes[i]; j < N; j *= primes[i]) pr[j] = true; 94 | } 95 | } 96 | 97 | 98 | void inline factor(int m) { 99 | len = 0; 100 | for (int i = 0; i < tot && primes[i] * primes[i] <= m; i++) { 101 | int j = primes[i]; 102 | if (m % j == 0) { 103 | d[len++] = j; 104 | while (m % j == 0) m /= j; 105 | } 106 | } 107 | if (m > 1) d[len++] = m; 108 | } 109 | 110 | int inline power(int a, int b, int P) { 111 | int res = 1; 112 | while (b) { 113 | if (b & 1) res = (LL)res * a % P; 114 | a = (LL)a * a % P; 115 | b >>= 1; 116 | } 117 | return res; 118 | } 119 | 120 | bool inline check(int x, int P) { 121 | if (power(x, phi[P], P) != 1) return false; 122 | for (int i = 0; i < len; i++) 123 | if(power(x, phi[P] / d[i], P) == 1) return false; 124 | return true; 125 | } 126 | 127 | // 输入 P,返回最小原根 128 | 129 | int inline get(int P) { 130 | for (int i = 1; i < P; i++) 131 | if (check(i, P)) return i; 132 | return 0; 133 | } 134 | 135 | // --- 136 | 137 | LL inline exgcd(LL a, LL b, LL &x, LL &y) { 138 | if (b == 0) { 139 | x = 1, y = 0; 140 | return a; 141 | } 142 | LL d = exgcd(b, a % b, y, x); 143 | y -= a / b * x; 144 | return d; 145 | } 146 | 147 | LL inline mod(LL a, LL b) { 148 | return (a % b + b) % b; 149 | } 150 | 151 | LL inline mul(LL a, LL b, LL p) { 152 | return ((a * b - (LL)((long double)a * b / p) * p) % p + p) % p; 153 | } 154 | 155 | int inline CRT() { 156 | LL M = 1; int res = 0; 157 | for (int i = 1; i <= n; i++) M *= m[i]; 158 | for (int i = 1; i <= n; i++) { 159 | LL x, y; 160 | LL d = exgcd(M / m[i], m[i], x, y); 161 | LL k = m[i] / d; 162 | x = (x % k + k) % k; 163 | res = (res + M / m[i] * a[i] * x) % M; 164 | } 165 | return res; 166 | } 167 | 168 | 169 | // 扩展中国剩余定理 exCRT 170 | typedef pair PLL; 171 | 172 | LL gcd(LL a, LL b) { 173 | return b ? gcd(b, a % b) : a; 174 | } 175 | 176 | LL exgcd(LL a, LL b, LL &x, LL &y) { 177 | if (!b) { 178 | x = 1, y = 0; 179 | return a; 180 | } 181 | LL d = exgcd(b, a % b, y, x); 182 | y -= a / b * x; 183 | return d; 184 | } 185 | 186 | LL mul(LL x, LL y, LL P) { 187 | return (__int128)x * y % P; 188 | // return x * y % P; 189 | } 190 | 191 | 192 | // x mod m = a (m1, a1) (m2, a2) return x 193 | 194 | PLL inline merge(PLL A, PLL B) { 195 | LL a1 = A.fi, b1 = A.se; 196 | LL a2 = B.fi, b2 = B.se; 197 | LL a = a1 / gcd(a1, a2) * a2; 198 | LL x, y; 199 | LL d = exgcd(a1, a2, x, y); 200 | assert((b2 - b1) % d == 0); 201 | x = mul(x, (b2 - b1) / d, a); 202 | if (x < 0) x += a; 203 | LL o = mul(x, a1, a) + b1; 204 | if (o >= a) o -= a; 205 | PLL c = mp(a, o); 206 | return c; 207 | } 208 | 209 | // BSGS 210 | unordered_map mp; 211 | 212 | int BSGS(int a, int b, int P) { 213 | int t = sqrt(P) + 1; mp.clear(); b %= P; 214 | for (int j = 0, s = b; j < t; j++) 215 | mp[s] = j, s = (LL)s * a % P; 216 | a = power(a, t, P); 217 | for (int i = 1, s = 1; i <= t; i++) { 218 | s = (LL)s * a % P; 219 | if (mp.count(s) && i * t - mp[s] >= 0) 220 | return i * t - mp[s]; 221 | } 222 | return -1; 223 | } 224 | 225 | int gcd(int a, int b) { 226 | return b ? gcd(b, a % b) : a; 227 | } 228 | 229 | int exBSGS(int a, int b, int P) { 230 | int x, y, d, A = 1, k = 0; 231 | while ((d = gcd(a, P)) > 1) { 232 | if (b % d) return -1; 233 | b /= d, P /= d, k++, A = (LL)A * (a / d) % P; 234 | if (A == b) return k; 235 | } 236 | exgcd(A, P, x, y); x = (x % P + P) % P; 237 | int res = BSGS(a, (LL)b * x % P, P); 238 | return res == -1 ? -1 : res + k; 239 | } 240 | 241 | const int N = 5000005, S = 3000; 242 | const LL INF = 9e18; 243 | 244 | LL p1[N], p2[S], m1[N], m2[S]; 245 | 246 | int n, primes[N], tot; 247 | 248 | bool vis[N]; 249 | 250 | // 杜教筛 phi 251 | LL s1(int x) { 252 | if (x < N) return p1[x]; 253 | else if (p2[n / x] != INF) return p2[n / x]; 254 | LL res = x * (x + 1ll) / 2; 255 | for (LL l = 2, r; l <= x; l = r + 1) { 256 | r = x / (x / l); 257 | res -= (r - l + 1) * s1(x / l); 258 | } 259 | return p2[n / x] = res; 260 | } 261 | 262 | // 杜教筛 mu 263 | 264 | LL s2(int x) { 265 | if (x < N) return m1[x]; 266 | else if (m2[n / x] != INF) return m2[n / x]; 267 | LL res = 1; 268 | for (LL l = 2, r; l <= x; l = r + 1) { 269 | r = x / (x / l); 270 | res -= (r - l + 1) * s2(x / l); 271 | } 272 | return m2[n / x] = res; 273 | } 274 | 275 | // 线性筛 276 | void inline linear() { 277 | m1[1] = p1[1] = 1; 278 | for (int i = 2; i < N; i++) { 279 | if (!vis[i]) primes[++tot] = i, m1[i] = -1, p1[i] = i - 1; 280 | for (int j = 1; i * primes[j] < N; j++) { 281 | vis[i * primes[j]] = true; 282 | if (i % primes[j] == 0) { 283 | p1[i * primes[j]] = p1[i] * primes[j]; 284 | break; 285 | } 286 | p1[i * primes[j]] = p1[i] * (primes[j] - 1); 287 | m1[i * primes[j]] = -m1[i]; 288 | } 289 | } 290 | } 291 | 292 | // 矩阵 293 | 294 | struct Mat{ 295 | int n, m, w[N][N]; 296 | Mat operator * (const Mat &b) const { 297 | Mat c; c.n = n, c.m = b.m; 298 | memset(c.w, 0, sizeof c.w); 299 | for (int i = 0; i < n; i++) 300 | for (int j = 0; j < b.m; j++) 301 | for (int k = 0; k < m; k++) 302 | c.w[i][j] = (c.w[i][j] + (LL)w[i][k] * b.w[k][j]) % P; 303 | return c; 304 | } 305 | Mat operator + (const Mat &b) const { 306 | Mat c; c.n = n, c.m = b.m; 307 | memset(c.w, 0, sizeof c.w); 308 | for (int i = 0; i < n; i++) 309 | for (int j = 0; j < b.m; j++) 310 | c.w[i][j] = (w[i][j] + b.w[i][j]) % P; 311 | return c; 312 | } 313 | } res; 314 | bool inline gauss() { 315 | int r, c; 316 | for (r = 1, c = 1; c <= n; c++) { 317 | int u = r; 318 | for (int i = r + 1; i <= n; i++) if (fabs(a[i][c]) > fabs(a[u][c])) u = i; 319 | if (fabs(a[u][c]) < eps) break; 320 | for (int i = c; i <= n + 1; i++) swap(a[r][i], a[u][i]); 321 | for (int i = n + 1; i >= c; i--) a[r][i] /= a[r][c]; 322 | for (int i = 1; i <= n; i++) { 323 | if (i != r) { 324 | for (int j = 1; j <= n + 1; j++) 325 | if (j != c) a[i][j] -= a[r][j] * a[i][c]; 326 | } 327 | } 328 | r++; 329 | } 330 | return r == n + 1; 331 | } 332 | 333 | 334 | // --- 行列式求值 335 | 336 | int inline det() { 337 | int res = 1, v = 1; 338 | for (int i = 1; i <= n; i++) { 339 | int t = -1; 340 | for (int j = i; j <= n; j++) 341 | if (a[j][i] && (t == -1 || a[j][i] > a[t][i])) t = j; 342 | if (t == -1) return 0; 343 | if (i != t) swap(a[t], a[i]), v *= -1; 344 | for (int j = i + 1; j <= n; j++) { 345 | if (a[j][i] > a[i][i]) swap(a[j], a[i]), v *= -1; 346 | while (a[j][i]) { 347 | int t = a[i][i] / a[j][i]; 348 | for (int k = i; k <= n; k++) { 349 | a[i][k] = (a[i][k] - 1ll * a[j][k] * t % P + P) % P; 350 | swap(a[j][k], a[i][k]); 351 | } 352 | v *= -1; 353 | } 354 | } 355 | res = (LL)res * a[i][i] % P; 356 | } 357 | return (LL)res * (v + P) % P; 358 | } 359 | 360 | // 拉格朗日插值 361 | 362 | int inline Interpo(int k, int n, int x[], int y[]){ 363 | int res = 0; 364 | for (int i = 1; i <= n; i++) { 365 | int v1 = y[i], v2 = 1; 366 | for (int j = 1; j <= n; j++) { 367 | if (i != j) { 368 | v1 = (LL) v1 * (K - x[j]) % P; 369 | v2 = (LL) v2 * (x[i] - x[j]) % P; 370 | } 371 | } 372 | res = ((res + (LL)v1 * power(v2, P - 2) % P) % P + P) % P; 373 | } 374 | return res; 375 | } 376 | 377 | // Min25 378 | 379 | int inv2 = power(2, P - 2), inv6 = power(6, P - 2); 380 | 381 | // 求 g_k 函数: <= x 的和 382 | int inline getS(LL x, int k) { 383 | if (k == 1) return (x % P * (x % P + 1ll) % P * inv2 + P - 1ll) % P; 384 | if (k == 2) return (P - 1ll + x % P * (x % P + 1ll) % P * (2ll * x % P + 1) % P * inv6) % P; 385 | } 386 | 387 | int inline getV(LL x, int k) { 388 | if (k == 1) return x % P; 389 | if (k == 2) return (LL)x % P * x % P; 390 | } 391 | 392 | bool vis[M]; 393 | 394 | int primes[M], tot; 395 | 396 | void inline linear(int n) { 397 | for (int i = 2; i <= n; i++) { 398 | if (!vis[i]) primes[++tot] = i; 399 | for (int j = 1; primes[j] <= n / i; j++) { 400 | vis[i * primes[j]] = true; 401 | if (i % primes[j] == 0) break; 402 | } 403 | } 404 | } 405 | 406 | // 预处理 g_k 处所有 n / i 形式的质数前缀和 407 | 408 | struct MP1{ 409 | int m, g[M], pos1[M], pos2[M], len, id; 410 | LL n, d[M]; 411 | int inline getPos(LL x) { 412 | return x <= m ? pos1[x] : pos2[n / x]; 413 | } 414 | void inline add(LL v) { 415 | d[++len] = v; 416 | g[len] = getS(v, id); 417 | if (v <= m) pos1[v] = len; 418 | else pos2[n / v] = len; 419 | } 420 | void build(LL sum, int t) { 421 | m = sqrt(n = sum); id = t; 422 | for (LL i = 1, j; i <= n; i = j + 1) { 423 | LL v = n / i; j = n / v; 424 | if (v <= m) break; 425 | add(v); 426 | } 427 | for (int i = m; i; i--) add(i); 428 | for (int i = 1; i <= tot && (LL)primes[i] * primes[i] <= n; i++) { 429 | LL pr = primes[i]; 430 | for (int j = 1; j <= len && pr * pr <= d[j]; j++) { 431 | int k = getPos(d[j] / pr); 432 | g[j] = (g[j] - (LL)getV(pr, id) * (g[k] - g[getPos(primes[i - 1])] + P) % P + P) % P; 433 | } 434 | } 435 | } 436 | int inline s(LL x) { return g[getPos(x)]; } 437 | } t1, t2; 438 | 439 | int inline get(LL x) { 440 | return (t2.s(x) - t1.s(x) + P) % P; 441 | } 442 | 443 | int inline calc(LL x) { 444 | return x % P * (x % P - 1ll + P) % P; 445 | } 446 | 447 | void inline add(int &x, int y) { 448 | (x += y) %= P; 449 | } 450 | 451 | int inline s(LL n, int t) { 452 | if (primes[t] >= n) return 0; 453 | int ans = (get(n) - get(primes[t]) + P) % P; 454 | for (int i = t + 1; i <= tot && (LL)primes[i] * primes[i] <= n; i++) { 455 | int pr = primes[i]; 456 | LL v = pr; 457 | for (int j = 1; v <= n; v = v * pr, j++) { 458 | add(ans, (LL)calc(v) * ((j != 1) + s(n / v, i)) % P); 459 | } 460 | } 461 | return ans; 462 | } 463 | 464 | //--- 465 | 466 | // FMT / FWT 467 | 468 | void inline OR(int n, int a[], int o) { 469 | for (int w = 1; w < n; w <<= 1) 470 | for (int i = 0; i < n; i += (w << 1)) 471 | for (int j = 0; j < w; j++) 472 | add(a[i + j + w], o * a[i + j]); 473 | } 474 | 475 | void inline AND(int n, int a[], int o) { 476 | for (int w = 1; w < n; w <<= 1) 477 | for (int i = 0; i < n; i += (w << 1)) 478 | for (int j = 0; j < w; j++) 479 | add(a[i + j], o * a[i + j + w]); 480 | } 481 | 482 | 483 | // 反向传 1/2 484 | void inline XOR(int n, int a[], int o) { 485 | for (int w = 1; w < n; w <<= 1) 486 | for (int i = 0; i < n; i += (w << 1)) 487 | for (int j = 0; j < w; j++) { 488 | int u = a[i + j], v = a[i + j + w]; 489 | a[i + j] = ((LL)u + v + P) * o % P; 490 | a[i + j + w] = ((LL)u - v + P) * o % P; 491 | } 492 | } 493 | 494 | // 子集卷积 495 | 496 | 497 | void inline SubConv(int n, int a[], int b[], int c[]) { 498 | for (int i = 0; i < (1 << n); i++) { 499 | f[get(i)][i] = a[i]; 500 | g[get(i)][i] = b[i]; 501 | } 502 | for (int i = 0; i <= n; i++) 503 | OR(1 << n, f[i], 1), OR(1 << n, g[i], 1); 504 | for (int i = 0; i <= n; i++) 505 | for (int j = 0; j <= i; j++) 506 | for (int k = 0; k < (1 << n); k++) 507 | add(h[i][k], (LL)f[j][k] * g[i - j][k] % P); 508 | for (int i = 0; i <= n; i++) OR(1 << n, h[i], -1); 509 | for (int i = 0; i < (1 << n); i++) c[i] = h[get(i)][i]; 510 | } 511 | 512 | // 矩阵求逆 513 | 514 | 515 | bool inline matInv(int n, int a[N][N], int b[N][N]) { 516 | int c[N][N << 1]; 517 | memset(c, 0, sizeof c); 518 | for (int i = 1; i <= n; i++) { 519 | for (int j = 1; j <= n; j++) c[i][j] = a[i][j]; 520 | c[i][i + n] = 1; 521 | } 522 | for (int i = 1; i <= n; i++) { 523 | int t = -1; 524 | for (int j = i; j <= n; j++) if (c[j][i]) t = j; 525 | if (t == -1) return false; 526 | if (t != i) swap(c[t], c[i]); 527 | int inv = power(c[i][i], P - 2); 528 | for (int j = 1; j <= 2 * n; j++) c[i][j] = (LL)c[i][j] * inv % P; 529 | for (int j = 1; j <= n; j++) { 530 | if (i == j) continue; 531 | int v = c[j][i]; 532 | if (!v) continue; 533 | for (int k = 1; k <= 2 * n; k++) 534 | c[j][k] = (c[j][k] - (LL)c[i][k] * v % P + P) % P; 535 | } 536 | } 537 | for (int i = 1; i <= n; i++) 538 | for (int j = 1; j <= n; j++) b[i][j] = c[i][j + n]; 539 | return true; 540 | } 541 | 542 | // St: 543 | 544 | namespace Red{ 545 | int MOD, I; 546 | 547 | struct Num{ 548 | int x, y; 549 | }; 550 | 551 | Num operator * (const Num a, const Num b) { 552 | return (Num) { (int)(((LL)a.x * b.x + (LL)I * a.y % P * b.y) % P) , (int)(((LL)a.x * b.y + (LL)a.y * b.x) % P) }; 553 | } 554 | 555 | 556 | Num inline power(Num a, int b) { 557 | Num res = (Num) { 1, 0 }; 558 | while (b) { 559 | if (b & 1) res = res * a; 560 | a = a * a; 561 | b >>= 1; 562 | } 563 | return res; 564 | } 565 | 566 | int inline EulerCri(int x) { 567 | return power(x, (MOD - 1) >> 1, MOD); 568 | } 569 | 570 | int inline Sqrt(int n, int o) { 571 | MOD = o; 572 | if (n == 0) return 0; 573 | if (EulerCri(n) == P - 1) return -1; 574 | int a = rand() % P, t; 575 | while (EulerCri(t = ((LL)a * a + MOD - n) % P) != MOD - 1) a = rand() % MOD; 576 | I = t; 577 | int x0 = power((Num) { a, 1 }, (P + 1) >> 1).x; 578 | return min(x0, P - x0); 579 | } 580 | } 581 | 582 | 583 | // _end 584 | 585 | // Exgcd 求逆 586 | 587 | int inline inv(int a, int P) { 588 | LL x, y; 589 | LL d = exgcd(a, P, x, y); 590 | LL k = P / d; 591 | x = (x % k + k) % k; 592 | return x; 593 | } 594 | 595 | // ExLucas 596 | 597 | 598 | namespace Cpk{ 599 | int h[M], p, k, v, P; 600 | void init(int Po, int K, int V) { 601 | p = Po, k = K, P = v = V; 602 | h[0] = 1; 603 | for (int i = 1; i <= v; i++) { 604 | h[i] = h[i - 1]; 605 | if (i % p) h[i] = (LL)h[i] * i % P; 606 | } 607 | } 608 | int inline f(LL n) { 609 | if (!n) return 1; 610 | return (LL)f(n / p) * power(h[v], n / v, v) % P * h[n % v] % P; 611 | } 612 | LL inline g(LL n) { 613 | LL res = 0; 614 | while (n) { 615 | res += n / p; 616 | n /= p; 617 | } 618 | return res; 619 | } 620 | int inline C(LL n, LL m) { 621 | return (LL)power(p, g(n) - g(m) - g(n - m), P) * f(n) % P * inv((LL)f(m) * f(n - m) % P, P) % P; 622 | } 623 | } 624 | 625 | int inline exLucas(LL n, LL m, int P) { 626 | for (int i = 2; i <= P; i++) { 627 | if (P % i == 0) { 628 | int k = 0, t = 1; 629 | while (P % i == 0) k++, P /= i, t *= i; 630 | ++len, p[len] = t; 631 | Cpk::init(i, k, t); 632 | a[len] = Cpk::C(n, m); 633 | } 634 | } 635 | return CRT(len); 636 | } 637 | 638 | // 639 | LL inline mul(LL a, LL b, LL P) { 640 | a %= P, b %= P; 641 | return ((a * b - (LL)((long double)a * b / P) * P) % P + P) % P; 642 | } 643 | 644 | LL inline power(LL a, LL b, LL Mod) { 645 | LL res = 1; 646 | while (b) { 647 | if (b & 1) res = mul(res, a, Mod); 648 | a = mul(a, a, Mod); 649 | b >>= 1; 650 | } 651 | return res; 652 | } 653 | 654 | class MillerRabin{ 655 | private: 656 | const int p[12] = { 2, 3, 5, 7, 11, 13, 17, 19, 61, 2333, 4567, 24251 }; 657 | bool inline check(LL x, int P) { 658 | if (x % P == 0 || power(P % x, x - 1, x) == 0) return false; 659 | LL k = x - 1; 660 | while (k % 2 == 0) { 661 | LL v = power(P % x, k >>= 1, x); 662 | if (v != 1 && v != x - 1) return false; 663 | if (v == x - 1) return true; 664 | } 665 | return true; 666 | } 667 | public: 668 | bool inline isPrime(LL x) { 669 | if (x < 2) return false; 670 | for (int i = 0; i < 12; i++) { 671 | if (p[i] == x) return true; 672 | if (!check(x, p[i])) return false; 673 | } 674 | return true; 675 | } 676 | } mr; 677 | 678 | // PollardRho 679 | 680 | LL inline Abs(LL x) { 681 | return x < 0 ? -x : x; 682 | } 683 | 684 | LL inline f(LL x, LL c, LL P) { 685 | return (mul(x, x, P) + c) % P; 686 | } 687 | 688 | LL gcd(LL a, LL b) { 689 | return b ? gcd(b, a % b) : a; 690 | } 691 | 692 | LL inline PollardRho(LL n) { 693 | LL c = (LL)rand() * rand() % (n - 1) + 1; 694 | LL p = 0, q = 0, v = 1; 695 | for (int i = 1; ; i <<= 1, p = q, v = 1) { 696 | for (int j = 0; j < i; j++) { 697 | q = f(q, c, n); 698 | v = mul(v, Abs(q - p), n); 699 | if (j % 100 == 0) { 700 | LL d = gcd(v, n); 701 | if (d > 1) return d; 702 | } 703 | } 704 | LL d = gcd(v, n); 705 | if (d > 1) return d; 706 | } 707 | return n; 708 | } 709 | 710 | LL n, ans; 711 | 712 | // 找最大质因子 713 | 714 | void fact(LL n) { 715 | if (n < 2 || n <= ans) return; 716 | if (mr.isPrime(n)) { 717 | if (n > ans) ans = n; 718 | return; 719 | } 720 | LL p = n; 721 | while (p >= n) p = PollardRho(n); 722 | while (n % p == 0) n /= p; 723 | fact(n), fact(p); 724 | } 725 | 726 | // _end 727 | 728 | 729 | // 线性基 730 | 731 | LL a[N]; 732 | 733 | int insert(LL x) { 734 | for (int i = L - 1; ~i; i--) { 735 | if(!(x >> i & 1)) continue; 736 | if (a[i]) x ^= a[i]; 737 | else { a[i] = x; return i; } 738 | } 739 | return -1; 740 | } 741 | 742 | // 动态插入一行的高斯消元(可撤销,就是直接复制) 743 | 744 | struct Gauss{ 745 | int a[N][N], m; 746 | bool o; 747 | void inline ins(int b[]) { 748 | for (int i = 1; i <= n + 1; i++) c[i] = b[i]; 749 | for (int i = 1; i <= n; i++) { 750 | if (c[i]) { 751 | if (!a[i][i]) { 752 | int inv = power(c[i], P - 2); 753 | for (int j = 1; j <= n + 1; j++) 754 | a[i][j] = (LL)c[j] * inv % P; 755 | for (int j = i + 1; j <= n; j++) { 756 | if (a[j][j] && a[i][j]) { 757 | int t = a[i][j]; 758 | for (int k = 1; k <= n + 1; k++) 759 | a[i][k] = (a[i][k] - 1ll * a[j][k] * t % P + P) % P; 760 | } 761 | } 762 | for (int j = 1; j < i; j++) { 763 | if (a[j][i]) { 764 | int t = a[j][i]; 765 | for (int k = 1; k <= n + 1; k++) 766 | a[j][k] = (a[j][k] - 1ll * a[i][k] * t % P + P) % P; 767 | } 768 | } 769 | ++m; 770 | return; 771 | } else { 772 | int t = c[i]; 773 | for (int j = 1; j <= n + 1; j++) 774 | c[j] = (c[j] - 1ll * t * a[i][j] % P + P) % P; 775 | } 776 | } 777 | } 778 | if (c[n + 1]) { 779 | o = 1; 780 | } 781 | } 782 | void inline sh() { 783 | for (int i = 1; i <= n; i++) { 784 | for (int j = 1; j <= n + 1; j++) cout << a[i][j] << " "; 785 | cout << endl; 786 | } 787 | } 788 | void inline out() { 789 | if (o) { 790 | puts("Impossible!"); 791 | } else { 792 | for (int i = 1; i <= m; i++) { 793 | for (int j = 1; j <= n + 1; j++) z[j] = 0; 794 | z[i] = 1; 795 | ins(z); 796 | } 797 | //puts("Succc!!"); 798 | memset(ans, 0, sizeof ans); 799 | for (int i = 1; i <= n; i++) { 800 | int p = 0; 801 | for (int j = 1; j <= n; j++) 802 | if (a[i][j]) p = j; 803 | ans[p] = a[i][n + 1]; 804 | } 805 | for (int i = 1; i <= n; i++) 806 | printf("%d ", ans[i]); 807 | puts(""); 808 | } 809 | } 810 | } t[15]; 811 | 812 | // 万能欧几里得 813 | 814 | struct Data{ 815 | } IN; 816 | // IN 无贡献时。 817 | 818 | 819 | // 信息合并 820 | Data operator + (const Data &a, const Data &b) { 821 | 822 | } 823 | 824 | // 信息叠加 b 次 825 | Data operator * (const Data &a, int b) { 826 | 827 | } 828 | 829 | Data calc(LL n, LL p, LL q, LL r, Data A, Data B) { 830 | if (!n) return IN; 831 | r %= q; 832 | if (p >= q) return calc(n, p % q, q, r, B * (p / q) + A, B); 833 | LL x = ((I)p * n + r) / q; 834 | if (!x) return A * n; 835 | return A * ((q - r - 1) / p) + B + calc(x - 1, q, p, q - r - 1, B, A) + A * (n - ((I)q * x - r - 1 + p) / p + 1); 836 | } -------------------------------------------------------------------------------- /数据结构.cpp: -------------------------------------------------------------------------------- 1 | // ST 表 2 | struct ST{ 3 | void inline STPrework(int n) { 4 | g[0] = -1; 5 | for (int i = 1; i <= n; i++) 6 | f[i][0] = a[i], g[i] = g[i >> 1] + 1; 7 | for (int j = 1; j <= g[n]; j++) 8 | for (int i = 1; i + (1 << j) - 1 <= n; i++) 9 | f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]); 10 | } 11 | 12 | int inline query(int l, int r) { 13 | int k = g[r - l + 1]; 14 | return max(f[l][k], f[r - (1 << k) + 1][k]); 15 | } 16 | } 17 | 18 | // 线性基 19 | struct Linear{ 20 | int idx = 1, tr[SZ * 32][2], cnt[SZ * 32]; 21 | void insert(LL x) { 22 | int p = 1; 23 | for (int i = 31; ~i; i--) { 24 | int ch = x >> i & 1; 25 | if (!tr[p][ch]) tr[p][ch] = ++idx; 26 | p = tr[p][ch], cnt[p]++; 27 | } 28 | } 29 | 30 | LL query(LL x, int k) { 31 | int p = 1; LL res = 0; 32 | for (int i = 31; ~i; i--) { 33 | int ch = x >> i & 1; 34 | if (k <= cnt[tr[p][!ch]]) res |= 1ll << i, p = tr[p][!ch]; 35 | else k -= cnt[tr[p][!ch]], p = tr[p][ch]; 36 | } 37 | return res; 38 | } 39 | } 40 | 41 | // 普通线段树 42 | 43 | struct Seg{ 44 | #define ls (p << 1) 45 | #define rs (p << 1 | 1) 46 | void inline pu(int p) { 47 | 48 | } 49 | 50 | void inline pd(int p) { 51 | 52 | } 53 | 54 | void bd(int p, int l, int r) { 55 | if(l == r) { 56 | return; 57 | } 58 | int mid = (l + r) >> 1; 59 | bd(ls, l, mid); 60 | bd(rs, mid + 1, r); 61 | pu(p); 62 | } 63 | void chg(int p, int l, int r, int x, int y, int k, int c) { 64 | if(x <= l && r <= y) { 65 | return ; 66 | } 67 | int mid = (l + r) >> 1; 68 | pd(p); 69 | if(x <= mid) chg(ls, l, mid, x, y, k, c); 70 | if(mid + 1 <= y) chg(rs, mid + 1, r, x, y, k, c); 71 | pu(p); 72 | } 73 | 74 | int qry(int p, int l, int r, int x, int y) { 75 | if(x <= l && r <= y) return ?; 76 | int mid = (l + r) >> 1, s = 0; 77 | pd(p); 78 | if(x <= mid) s += qry(ls, l, mid, x, y); 79 | if(mid + 1 <= y) s += qry(rs, mid + 1, r, x, y); 80 | return s % P; 81 | } 82 | } 83 | 84 | // 用来动态开点的池 85 | struct T{ 86 | int l, r, val, rnd, sz; 87 | } t[SZ]; 88 | int idx; 89 | 90 | 91 | struct Fhq{ 92 | int rt; 93 | void pushup(int p) { 94 | 95 | } 96 | // value(A) < value(B) 97 | int merge(int A, int B) { 98 | if (!A || !B) return A + B; 99 | else if(t[A].rnd > t[B].rnd) { 100 | t[A].r = merge(t[A].r, B); 101 | pushup(A); 102 | return A; 103 | } else { 104 | t[B].l = merge(A, t[B].l); 105 | pushup(B); 106 | return B; 107 | } 108 | } 109 | 110 | // 按值分裂 111 | void split(int p, int k, int &x, int &y) { 112 | if (!p) x = y = 0; 113 | else { 114 | if (t[p].val <= k) 115 | x = p, split(t[p].r, k, t[p].r, y); 116 | else y = p, split(t[p].l, k, x, t[p].l); 117 | pushup(p); 118 | } 119 | } 120 | int getNode(int val) { 121 | t[++idx] = (T) { 0, 0, val, rand(), 1 }; 122 | return idx; 123 | } 124 | 125 | void insert(int val) { 126 | int x, y; 127 | split(rt, val, x, y); 128 | rt = merge(merge(x, getNode(val)), y); 129 | } 130 | 131 | int get(int l, int r) { 132 | int x, y, z; 133 | split(rt, l - 1, x, y); 134 | split(y, r, y, z); 135 | int res = t[y].N; 136 | rt = merge(x, merge(y, z)); 137 | return res; 138 | } 139 | 140 | void del(int val) { 141 | int x, y, z; 142 | split(rt, val - 1, x, y); 143 | split(y, val, y, z); 144 | y = merge(t[y].l, t[y].r); 145 | rt = merge(x, merge(y, z)); 146 | } 147 | } 148 | 149 | struct LCT{ 150 | #define get(x) (ch[fa[x]][1] == x) 151 | #define isRoot(x) (ch[fa[x]][0] != x && ch[fa[x]][1] != x) 152 | #define ls ch[p][0] 153 | #define rs ch[p][1] 154 | 155 | int ch[N][2], fa[N], mx[N], w[N], rev[N]; 156 | 157 | void inline pushup(int p) { 158 | 159 | } 160 | 161 | void inline pushdown(int p) { 162 | if (rev[p]) { swap(ls, rs), rev[ls] ^= 1, rev[rs] ^= 1, rev[p] = 0; } 163 | } 164 | 165 | void inline rotate(int x) { 166 | int y = fa[x], z = fa[y], k = get(x); 167 | if (!isRoot(y)) ch[z][get(y)] = x; 168 | ch[y][k] = ch[x][!k], fa[ch[y][k]] = y; 169 | ch[x][!k] = y, fa[y] = x, fa[x] = z; 170 | pushup(y); pushup(x); 171 | } 172 | 173 | void inline update(int p) { 174 | if (!isRoot(p)) update(fa[p]); 175 | pushdown(p); 176 | } 177 | 178 | void inline splay(int p) { 179 | update(p); 180 | for (int f = fa[p]; !isRoot(p); rotate(p), f = fa[p]) 181 | if (!isRoot(f)) rotate(get(p) == get(f) ? f : p); 182 | } 183 | 184 | void inline access(int x) { 185 | for (int p = 0; x; p = x, x = fa[x]) { 186 | splay(x), ch[x][1] = p, pushup(x); 187 | } 188 | } 189 | 190 | int inline find(int p) { 191 | access(p), splay(p); 192 | while (ls) pushdown(p), p = ls; 193 | splay(p); 194 | return p; 195 | } 196 | 197 | void inline makeRoot(int x) { 198 | access(x), splay(x), rev[x] ^= 1; 199 | } 200 | 201 | void inline split(int x, int y) { 202 | makeRoot(x), access(y), splay(y); 203 | } 204 | 205 | void inline link(int x, int y) { 206 | makeRoot(x), fa[x] = y; 207 | } 208 | 209 | void inline cut(int x, int y) { 210 | split(x, y); 211 | ch[y][0] = 0, fa[x] = 0; 212 | pushup(y); 213 | } 214 | 215 | } 216 | 217 | // 主席树 218 | struct PersisSeg{ 219 | struct T{ 220 | int l, r; 221 | LL v; 222 | } t[SZ]; 223 | 224 | int rt[SZ], idx; 225 | 226 | void inline update(int &p, int q, int l, int r, int x, int k) { 227 | t[p = ++idx] = t[q]; 228 | t[p].v += k; 229 | if (l == r) return; 230 | int mid = (l + r) >> 1; 231 | if (x <= mid) update(t[p].l, t[q].l, l, mid, x, k); 232 | else update(t[p].r, t[q].r, mid + 1, r, x, k); 233 | } 234 | 235 | LL inline query(int p, int l, int r, int x, int y) { 236 | if (!p || x > y) return 0; 237 | if (x <= l && r <= y) return t[p].v; 238 | int mid = (l + r) >> 1; LL res = 0; 239 | if (x <= mid) res += query(t[p].l, l, mid, x, y); 240 | if (mid < y) res += query(t[p].r, mid + 1, r, x, y); 241 | return res; 242 | } 243 | } 244 | 245 | 246 | // 并查集 247 | struct DSU{ 248 | int f[N], sz[N]; 249 | void init(int n) { for (int i = 1; i <= n; i++) f[i] = i, sz[i] = 1; } 250 | int inline find(int x) { return f[x] == x ? x : f[x] = find(f[x]); } 251 | void inline merge(int x, int y) { 252 | x = find(x), y = find(y); 253 | if (x == y) return; 254 | if (sz[x] > sz[y]) swap(x, y); 255 | sz[y] += sz[x], f[x] = y; 256 | } 257 | }; 258 | 259 | // 树状数组 260 | 261 | struct BIT{ 262 | int n; 263 | LL c[SZ]; 264 | void inline init(int len, LL a[]) { 265 | n = len; 266 | for (int i = 1; i <= n; i++) { 267 | c[i] += a[i]; 268 | if (i + (i & -i) <= n) c[i + (i & -i)] += c[i]; 269 | } 270 | } 271 | void inline add(int x, LL k) { 272 | for (; x <= n; x += x & -x) c[x] += k; 273 | } 274 | LL inline ask(int x) { 275 | LL res = 0; 276 | for (; x; x -= x & -x) res += c[x]; 277 | return res; 278 | } 279 | } ; 280 | 281 | // 区间加 区间查的树状数组 282 | struct exBIT{ 283 | BIT t1, t2; 284 | int n; 285 | void inline init(int len, int a[]) { 286 | n = len; 287 | for (int i = 1; i <= n; i++) 288 | b[i] = a[i] - a[i - 1]; 289 | t1.init(n, b); 290 | for (int i = 1; i <= n; i++) b[i] *= i; 291 | t2.init(n, b); 292 | } 293 | void inline add(int l, int r, LL c) { 294 | t1.add(l, c), t1.add(r + 1, -c); 295 | t2.add(l, c * l), t2.add(r + 1, -c * (r + 1)); 296 | } 297 | LL inline ask(int x) { 298 | return (x + 1) * t1.ask(x) - t2.ask(x); 299 | } 300 | LL inline ask(int x, int y) { return ask(y) - ask(x - 1); } 301 | }; 302 | 303 | // 左偏树 304 | 305 | struct LeftistTree{ 306 | struct T{ 307 | int l, r, v, d, f; 308 | // l, r 表示左右儿子, v 表示值 309 | // d 表示从当前节点到最近叶子节点的距离, f 表示当前节点的父亲 310 | } t[SZ]; 311 | 312 | int find(int x) { 313 | return t[x].f == x ? x : t[x].f = find(t[x].f); 314 | } 315 | 316 | int merge(int x, int y) { // 递归合并函数 317 | if (!x || !y) return x + y; 318 | if (t[x].v > t[y].v || (t[x].v == t[y].v && x > y)) swap(x, y); 319 | rs = merge(rs, y); 320 | if (t[ls].d < t[rs].d) swap(ls, rs); 321 | t[x].d = t[rs].d + 1; 322 | return x; 323 | } 324 | 325 | int work(int x, int y) { // 合并 x, y 两个堆。 326 | if (x == y) return 0; 327 | if (!x || !y) return t[x + y].f = x + y; 328 | if (t[x].v > t[y].v || (t[x].v == t[y].v && x > y)) swap(x, y); 329 | t[x].f = t[y].f = x; 330 | merge(x, y); return x; 331 | } 332 | 333 | void del(int x) { 334 | t[x].f = work(ls, rs), t[x].v = -1; 335 | } 336 | } 337 | 338 | 339 | 340 | // 后缀自动机 + DAG 剖分 341 | 342 | struct SAM_{ 343 | int nxt[26], len, link; 344 | }; 345 | 346 | // n 长度 347 | 348 | struct SAM{ 349 | SAM_ t[N << 1]; 350 | int last, idx, pos[N << 1], fa[N << 1][S]; 351 | vector g[N << 1]; 352 | int s[N]; 353 | void inline extend(int c) { 354 | int x = ++idx, p = last; t[x].len = t[p].len + 1; 355 | while (p && !t[p].nxt[c]) 356 | t[p].nxt[c] = x, p = t[p].link; 357 | if (!p) t[x].link = 1; 358 | else { 359 | int q = t[p].nxt[c]; 360 | if (t[p].len + 1 == t[q].len) t[x].link = q; 361 | else { 362 | int y = ++idx; t[y] = t[q]; 363 | t[y].len = t[p].len + 1; 364 | while (p && t[p].nxt[c] == q) 365 | t[p].nxt[c] = y, p = t[p].link; 366 | t[x].link = t[q].link = y; 367 | } 368 | } 369 | last = x; 370 | } 371 | int st[N << 2][S], Lg[N << 2], loc[N << 2], scnt, ind[N], Lf[N << 1], Rf[N << 1]; 372 | 373 | // ind 以 i 为后缀的点 374 | void inline build(int a[], int n) { 375 | last = idx = 1; 376 | // buildTree 377 | for (int i = 1; i <= n; i++) extend(a[i]), pos[last] = i, ind[i] = last, s[i] = a[i]; 378 | for (int i = 2; i <= idx; i++) g[t[i].link].pb(i), fa[i][0] = t[i].link; 379 | 380 | } 381 | 382 | void dfsf(int u) { 383 | for (int i = 1; i < S; i++) 384 | fa[u][i] = fa[fa[u][i - 1]][i - 1]; 385 | for (int v: g[u]) { 386 | dfsf(v); 387 | pos[u] = pos[v]; 388 | } 389 | } 390 | 391 | // 维护倍增祖先,以及每个点的任意一个 endpos(于 pos 392 | 393 | void inline buildFA() { 394 | // endpos - fa 395 | dfsf(1); 396 | } 397 | 398 | void dfsl(int u) { 399 | Lf[u] = ++scnt; 400 | st[scnt][0] = t[u].len; 401 | 402 | for (int v: g[u]) { 403 | dfsl(v); 404 | st[++scnt][0] = t[u].len; 405 | } 406 | } 407 | 408 | // 最长公共后缀预处理:ST 表 409 | 410 | void inline buildLSP() { 411 | dfsl(1); 412 | Lg[0] = -1; 413 | for (int i = 1; i <= scnt; i++) Lg[i] = Lg[i >> 1] + 1; 414 | for (int j = 1; j <= Lg[scnt]; j++) { 415 | for (int i = 1; i + (1 << j) - 1 <= scnt; i++) { 416 | st[i][j] = min(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]); 417 | } 418 | } 419 | } 420 | 421 | // 倍增定位长度为 l 的子串 422 | 423 | int inline fixPos(int p, int l) { 424 | for (int i = S - 1; ~i; i--) 425 | if (fa[p][i] && t[fa[p][i]].len >= l) p = fa[p][i]; 426 | return p; 427 | } 428 | 429 | // 最长公共后缀 430 | 431 | int inline lsp(int i, int j) { 432 | int l = Lf[ind[i]], r = Lf[ind[j]]; 433 | if (l > r) swap(l, r); 434 | int k = Lg[r - l + 1]; 435 | return min(st[l][k], st[r - (1 << k) + 1][k]); 436 | } 437 | int d[N << 2], tot; 438 | 439 | LL F[N << 1], G[N << 1]; 440 | 441 | bool vis[N << 1]; 442 | 443 | void dfs2(int u) { 444 | vis[u] = 1; 445 | for (int i = 0; i < 26; i++) { 446 | int v = t[u].nxt[i]; 447 | if (v && !vis[v]) dfs2(v); 448 | } 449 | d[++tot] = u; 450 | } 451 | 452 | int dfn[N << 1], dfncnt, ed[N << 1], pre[N << 1], top[N << 1]; 453 | 454 | void dfs3(int u, int tp) { 455 | dfn[u] = ++dfncnt; pre[dfn[u]] = u; 456 | top[u] = tp; 457 | for (int i = 0; i < 26; i++) { 458 | int v = t[u].nxt[i]; 459 | if (v && !dfn[v] && F[v] < F[u] * 2 && G[u] < G[v] * 2) dfs3(v, tp); 460 | } 461 | ed[u] = pre[dfncnt]; 462 | } 463 | 464 | // DAG 剖分。dfn 序列。 465 | 466 | void inline chainDiv() { 467 | dfs2(1); 468 | memset(vis, 0, sizeof vis); 469 | F[1] = 1; 470 | for (int i = 1; i <= idx; i++) G[i] = 1; 471 | for (int j = idx; j; j--) { 472 | int u = d[j]; 473 | for (int i = 0; i < 26; i++) { 474 | int v = t[u].nxt[i]; 475 | if (v) F[v] += F[u]; 476 | } 477 | } 478 | for (int j = 1; j <= idx; j++) { 479 | int u = d[j]; 480 | for (int i = 0; i < 26; i++) { 481 | int v = t[u].nxt[i]; 482 | if (v) G[u] += G[v]; 483 | } 484 | } 485 | for (int j = idx; j; j--) { 486 | int u = d[j]; 487 | if (!dfn[u]) dfs3(u, u); 488 | } 489 | } 490 | } 491 | 492 | // Cdq 分治 493 | 494 | void cdq(int l, int r) { 495 | if (l == r) return; 496 | int mid = (l + r) >> 1; 497 | cdq(l, mid), cdq(mid + 1, r); 498 | // Do sth 499 | 500 | } 501 | 502 | // 503 | 504 | // 莫队 505 | 506 | int pos[N], L[N], R[N], t; 507 | 508 | struct Q { 509 | int l, r, id; 510 | bool operator < (const Q &b) const { 511 | if (pos[l] != pos[b.l]) return pos[l] < pos[b.l]; 512 | return r < b.r; 513 | } 514 | } q[N]; 515 | 516 | t = sqrt(n); 517 | for (int i = 1; i <= n; i++) { 518 | pos[i] = (i - 1) / t + 1; 519 | if (!L[pos[i]]) L[pos[i]] = i; 520 | R[pos[i]] = i; 521 | } 522 | 523 | sort(q + 1, q + 1 + m); 524 | 525 | // 回滚 526 | 527 | int l = 1, r = 0, last = -1; 528 | for (int i = 1; i <= m; i++) { 529 | if (pos[q[i].l] == pos[q[i].r]) { 530 | // 块内暴力 531 | continue; 532 | } 533 | if (pos[q[i].l] != last) { 534 | // 新的左块 535 | res = 0, top = 0, r = R[pos[q[i].l]], l = r + 1; 536 | last = pos[q[i].l]; 537 | } 538 | while (r < q[i].r) { 539 | ++r; 540 | // insert r 541 | } 542 | int bl = l, tp = res; // 记录 543 | while (l > q[i].l) { 544 | --l; 545 | // insert l 546 | } 547 | // 恢复 548 | ans[q[i].id] = res; res = tp; 549 | } 550 | 551 | // End 552 | 553 | // DLX 1精确覆盖 554 | 555 | namespace DLX1{ 556 | int n, m, U[N], D[N], L[N], R[N], idx, s[N], hh, tt, X[N], Y[N]; 557 | 558 | int ans[M], top; 559 | 560 | void inline init() { 561 | for (int i = 0; i <= m; i++) 562 | L[i] = i - 1, R[i] = i + 1, U[i] = D[i] = i; 563 | L[0] = m, R[m] = 0, idx = m; 564 | } 565 | 566 | void inline add(int x, int y) { 567 | X[++idx] = x, Y[idx] = y, s[y]++; 568 | L[idx] = hh, R[idx] = tt, L[tt] = R[hh] = idx; 569 | U[idx] = U[y], D[idx] = y, D[U[y]] = idx, U[y] = idx; 570 | hh = idx; 571 | } 572 | 573 | // 删除第 p 列 574 | 575 | void del(int p) { 576 | L[R[p]] = L[p], R[L[p]] = R[p]; 577 | for (int i = D[p]; i != p; i = D[i]) { 578 | for (int j = R[i]; j != i; j = R[j]) { 579 | s[Y[j]]--, U[D[j]] = U[j], D[U[j]] = D[j]; 580 | } 581 | } 582 | } 583 | 584 | void resume(int p) { 585 | L[R[p]] = p, R[L[p]] = p; 586 | for (int i = U[p]; i != p; i = U[i]) { 587 | for (int j = L[i]; j != i; j = L[j]) { 588 | s[Y[j]]++, U[D[j]] = j, D[U[j]] = j; 589 | } 590 | } 591 | } 592 | 593 | bool inline dfs() { 594 | if (!R[0]) return true; 595 | int p = R[0]; 596 | for (int i = R[0]; i; i = R[i]) 597 | if (s[i] < s[p]) p = i; 598 | if (!s[p]) return false; 599 | del(p); 600 | for (int i = D[p]; i != p; i = D[i]) { 601 | ans[++top] = X[i]; 602 | for (int j = R[i]; j != i; j = R[j]) del(Y[j]); 603 | if (dfs()) return true; 604 | for (int j = L[i]; j != i; j = L[j]) resume(Y[j]); 605 | --top; 606 | } 607 | resume(p); 608 | return false; 609 | } 610 | main:: 611 | add(i, j) if (i, j) = 1 612 | dfs() 613 | } 614 | 615 | namespace DLX2{ 616 | int n, m, U[N], D[N], L[N], R[N], idx, s[N], hh, tt, X[N], Y[N]; 617 | 618 | int ans[M], top, dep, d[M]; 619 | 620 | bool st[N]; 621 | 622 | void inline init() { 623 | for (int i = 0; i <= m; i++) 624 | L[i] = i - 1, R[i] = i + 1, U[i] = D[i] = i; 625 | L[0] = m, R[m] = 0, idx = m; 626 | } 627 | 628 | void inline add(int x, int y) { 629 | X[++idx] = x, Y[idx] = y, s[y]++; 630 | L[idx] = hh, R[idx] = tt, L[tt] = R[hh] = idx; 631 | U[idx] = U[y], D[idx] = y, D[U[y]] = idx, U[y] = idx; 632 | hh = idx; 633 | } 634 | 635 | // 删除第 p 列 636 | 637 | void inline del(int p) { 638 | for (int i = D[p]; i != p; i = D[i]) 639 | L[R[i]] = L[i], R[L[i]] = R[i]; 640 | } 641 | 642 | void resume(int p) { 643 | for (int i = U[p]; i != p; i = U[i]) 644 | L[R[i]] = i, R[L[i]] = i; 645 | } 646 | 647 | int inline h() { 648 | memset(st, false, sizeof st); 649 | int cnt = 0; 650 | for (int i = R[0]; i; i = R[i]) { 651 | if (st[i]) continue; 652 | cnt++; 653 | for (int j = D[i]; j != i; j = D[j]) 654 | for (int k = R[j]; k != j; k = R[k]) st[Y[k]] = true; 655 | } 656 | return cnt; 657 | } 658 | 659 | bool inline dfs() { 660 | if (top + h() > dep) return false; 661 | if (!R[0]) return true; 662 | int p = R[0]; 663 | for (int i = R[0]; i; i = R[i]) 664 | if (s[i] < s[p]) p = i; 665 | if (!s[p]) return false; 666 | for (int i = D[p]; i != p; i = D[i]) { 667 | ans[++top] = X[i]; 668 | del(i); 669 | for (int j = R[i]; j != i; j = R[j]) del(j); 670 | if (dfs()) return true; 671 | for (int j = L[i]; j != i; j = L[j]) resume(j); 672 | resume(i); 673 | --top; 674 | } 675 | return false; 676 | } 677 | 678 | // m 行数 init 679 | main:: 680 | // 每一行 hh = tt = idx + 1; 681 | add(i, j) if (i, j) = 1 682 | dep = 1; 683 | while(!dfs()) dep++; 684 | printf("%d\n", dep); 685 | for (int i = 1; i <= dep; i++) printf("%d ", ans[i]); 686 | 687 | } 688 | 689 | 690 | typedef pair PII; 691 | typedef set::iterator SIT; 692 | typedef set SI; 693 | 694 | PII operator - (const PII &a, const PII &b) { 695 | return mp(a.x - b.x, a.y - b.y); 696 | } 697 | 698 | LL inline cross(PII a, PII b) { 699 | return a.x * b.y - a.y * b.x; 700 | } 701 | 702 | LL inline cross(PII a, PII b, PII c) { 703 | PII u = b - a, v = c - a; 704 | return cross(u, v); 705 | } 706 | 707 | 708 | // 珂朵莉树?? 709 | 710 | struct E{ 711 | int l, r, v; 712 | bool operator < (const E &b) const { 713 | return r < b.r; 714 | } 715 | }; 716 | 717 | set s; 718 | 719 | typedef set::iterator SIT; 720 | 721 | void split(int i) { 722 | SIT u = s.lower_bound((E){ 0, i + 1, 0 }); 723 | if (u == s.end()) return; 724 | if (u -> r > i && u -> l <= i) { 725 | E t = *u; 726 | s.erase(u); 727 | s.insert((E){ t.l, i, t.v }); 728 | s.insert((E){ i + 1, t.r, t.v }); 729 | } 730 | } 731 | 732 | void inline ins(int l, int r, int v) { 733 | split(l - 1), split(r); 734 | while (1) { 735 | SIT u = s.lower_bound((E){ 0, l, 0, 0 }); 736 | if (u == s.end()) break; 737 | if (u -> r > r) break; 738 | 739 | s.erase(u); 740 | } 741 | s.insert((E){ l, r, v }); 742 | } 743 | 744 | // Hashmap 745 | 746 | 747 | struct E{ 748 | int next, v, w; 749 | }; 750 | 751 | const int MOD = 999997; 752 | 753 | struct Hash{ 754 | E e[MOD]; 755 | int numE, head[MOD]; 756 | void inline clear() { 757 | for (int i = 1; i <= numE; i++) 758 | head[e[i].v % MOD] = 0; 759 | numE = 0; 760 | } 761 | int &operator[] (int x) { 762 | int t = x % MOD; 763 | for (int i = head[t]; i; i = e[i].next) { 764 | if (e[i].v == x) { 765 | return e[i].w; 766 | } 767 | } 768 | e[++numE] = (E) { head[t], x, 0 }; 769 | head[t] = numE; 770 | return e[numE].w; 771 | } 772 | } t 773 | 774 | 775 | // 李超树 776 | 777 | struct Line{ 778 | LL k, b; 779 | }; 780 | 781 | struct Tree{ 782 | int l, r; 783 | Line v; 784 | } t[N * 22]; 785 | 786 | int idx; 787 | 788 | struct LC{ 789 | // 最小值 / 下凸壳 790 | LL inline calc(Line e, LL x) { 791 | return e.k * x + e.b; 792 | } 793 | int rt; 794 | void inline clr() { 795 | rt = 0; 796 | } 797 | // 这里写法非常简洁的原因是,让计算机人工帮你判断了单调 / 需要 upd 的位置,事实上只会走一边。 798 | void inline ins(int &p, int l, int r, Line e) { 799 | if (!p) { 800 | t[p = ++idx] = (Tree) { 0, 0, e }; 801 | return; 802 | } 803 | int mid = (l + r) >> 1; 804 | if (calc(t[p].v, mid) > calc(e, mid)) swap(e, t[p].v); 805 | if (calc(e, l) < calc(t[p].v, l)) ins(t[p].l, l, mid, e); 806 | if (calc(e, r) < calc(t[p].v, r)) ins(t[p].r, mid + 1, r, e); 807 | } 808 | LL ask(int p, int l, int r, int x) { 809 | if (!p) return INF; 810 | if (l == r) return calc(t[p].v, x); 811 | int mid = (l + r) >> 1; LL ret = calc(t[p].v, x); 812 | if (x <= mid) chkMin(ret, ask(t[p].l, l, mid, x)); 813 | else chkMin(ret, ask(t[p].r, mid + 1, r, x)); 814 | return ret; 815 | } 816 | LL ask(int x) { 817 | return ask(rt, 1, LEN, x); 818 | } 819 | 820 | } lc[N]; 821 | 822 | // 全局平衡二叉树 823 | 824 | 825 | vector g[N]; 826 | 827 | int lim[N]; 828 | 829 | bool vis[N]; 830 | 831 | int fa[N], sz[N], son[N], d[N]; 832 | 833 | struct Mat{ 834 | // 定义矩阵的地方 835 | Mat operator * (const Mat &b) const { 836 | 837 | } 838 | }; 839 | 840 | void dfs1(int u) { 841 | sz[u] = 1; 842 | for (int v: g[u]) { 843 | if (v == fa[u]) continue; 844 | fa[v] = u; 845 | d[v] = d[u] + 1; 846 | dfs1(v); 847 | sz[u] += sz[v]; 848 | if (sz[v] > sz[son[u]]) son[u] = v; 849 | } 850 | } 851 | 852 | int len, b[N], val[N], rt[N], ps[N]; 853 | 854 | struct T{ 855 | int l, r, f; 856 | Mat v, s; 857 | } t[N]; 858 | 859 | int inline getM(int x, int y) { 860 | int mn = 2e9, p = -1; 861 | for (int i = x; i <= y; i++) 862 | if (chkMin(mn, max(val[i - 1] - val[x - 1], val[y] - val[i]))) p = i; 863 | return p; 864 | } 865 | 866 | #define ls t[p].l 867 | #define rs t[p].r 868 | 869 | void pu(int p) { 870 | if (ls && rs) t[p].s = t[rs].s * t[p].v * t[ls].s; 871 | else if (ls) t[p].s = t[p].v * t[ls].s; 872 | else if (rs) t[p].s = t[rs].s * t[p].v; 873 | else t[p].s = t[p].v; 874 | } 875 | 876 | void inline bd(int &p, int l, int r, int F) { 877 | if (l > r) return; 878 | int mid = getM(l, r); 879 | p = b[mid]; 880 | t[p].f = F; 881 | bd(ls, l, mid - 1, p), bd(rs, mid + 1, r, p); 882 | pu(p); 883 | } 884 | 885 | void inline remake(int u) { 886 | // 更新 u 的子树了,更新矩阵 887 | } 888 | 889 | void inline updF(int v) { 890 | // u 的轻儿子 v 变了,更新轻儿子对自己的影响 891 | } 892 | 893 | void inline bd(int tp) { 894 | int x = tp; vector z; 895 | while (x) z.pb(x), x = son[x]; 896 | for (int u: z) { 897 | for (int v: g[u]) 898 | if (v != fa[u] && v != son[u]) bd(v), updF(v); 899 | remake(u); 900 | } 901 | len = 0; 902 | for (int v: z) b[++len] = v, val[len] = sz[v] - sz[son[v]]; 903 | for (int i = 1; i <= len; i++) val[i] += val[i - 1]; 904 | bd(rt[tp], 1, len, 0); 905 | ps[rt[tp]] = tp; 906 | } 907 | 908 | void inline sop(int x) { 909 | while (x) { 910 | remake(x); int p = x, y = 0; 911 | while (p) y = ps[p], pu(p), p = t[p].f; 912 | if (!fa[y]) break; 913 | updF(y), x = fa[y]; 914 | } 915 | } 916 | 917 | // K-D Tree 918 | 919 | struct Node{ 920 | int x[2], l, r, L, R; 921 | bool operator < (const Node &b) const { 922 | return x[D] < b.x[D]; 923 | } 924 | } t[N]; 925 | 926 | #define ls t[p].l 927 | #define rs t[p].r 928 | 929 | 930 | void pu(int p) { 931 | // pushup 932 | } 933 | 934 | void inline pd(int p) { 935 | // pushdown 936 | } 937 | 938 | void bd(int &p, int l, int r, int z) { 939 | int len = r - l + 1; 940 | D = z; 941 | int mid = (l + r) >> 1; 942 | nth_element(t + l, t + mid, t + 1 + r); 943 | p = mid; 944 | t[p].L = l, t[p].R = r; 945 | if (l != mid) bd(ls, l, mid - 1, z ^ 1), t[ls].f = p; 946 | if (mid != r) bd(rs, mid + 1, r, z ^ 1), t[rs].f = p; 947 | pu(p); 948 | } 949 | 950 | 951 | void chg(int p, int l, int r, int x, int k) { 952 | // return 条件 953 | int mid = (l + r) >> 1; pd(p); 954 | // chg p 955 | if (l != mid) chg(ls, l, mid - 1, x, k); 956 | if (mid != r) chg(rs, mid + 1, r, x, k); 957 | pu(p); 958 | } 959 | 960 | void update(int p) { 961 | if (t[p].f) update(t[p].f); 962 | pd(p); 963 | } 964 | 965 | // 自底向上 966 | 967 | void inline fl(int x) { 968 | int p = pos[x]; 969 | update(p); 970 | // chg x 971 | while (p) { 972 | pu(p); p = t[p].f; 973 | } 974 | } 975 | 976 | 977 | // 线段树合并与分裂 978 | 979 | struct Seg{ 980 | int idx; 981 | 982 | struct T{ 983 | int l, r; 984 | LL v; 985 | } t[N * 22]; 986 | 987 | void inline pushup(int p) { 988 | t[p].v = t[t[p].l].v + t[t[p].r].v; 989 | } 990 | 991 | void build(int &p, int l, int r) { 992 | if (!p) p = ++idx; 993 | if (l == r) { 994 | t[p].v = a[l]; 995 | return; 996 | } 997 | int mid = (l + r) >> 1; 998 | build(t[p].l, l, mid); 999 | build(t[p].r, mid + 1, r); 1000 | pushup(p); 1001 | } 1002 | 1003 | void change(int &p, int &q, int l, int r, int x, int y) { 1004 | if (x <= l && r <= y) { 1005 | q = p; p = 0; 1006 | return; 1007 | } 1008 | if (!q) q = ++idx; 1009 | int mid = (l + r) >> 1; 1010 | if (x <= mid) change(t[p].l, t[q].l, l, mid, x, y); 1011 | if (mid < y) change(t[p].r, t[q].r, mid + 1, r, x, y); 1012 | pushup(p); pushup(q); 1013 | } 1014 | 1015 | void merge(int &p, int &q, int l, int r) { 1016 | if (!p) return; 1017 | if (!q) { q = p; return; } 1018 | if (l == r) { t[q].v += t[p].v; return; } 1019 | int mid = (l + r) >> 1; 1020 | merge(t[p].l, t[q].l, l, mid); 1021 | merge(t[p].r, t[q].r, mid + 1, r); 1022 | pushup(q); 1023 | } 1024 | 1025 | void insert(int &p, int l, int r, int x, int k) { 1026 | if (!p) p = ++idx; 1027 | if (l == r) { t[p].v += k; return ; } 1028 | int mid = (l + r) >> 1; 1029 | if (x <= mid) insert(t[p].l, l, mid, x, k); 1030 | else insert(t[p].r, mid + 1, r, x, k); 1031 | pushup(p); 1032 | } 1033 | 1034 | LL query(int p, int l, int r, int x, int y) { 1035 | if (!p) return 0; 1036 | if (x <= l && r <= y) return t[p].v; 1037 | int mid = (l + r) >> 1; LL res = 0; 1038 | if (x <= mid) res += query(t[p].l, l, mid, x, y); 1039 | if (mid < y) res += query(t[p].r, mid + 1, r, x, y); 1040 | return res; 1041 | } 1042 | 1043 | int kth(int p, int l, int r, int k) { 1044 | if (l == r) return l; 1045 | int mid = (l + r) >> 1; 1046 | if (k <= t[t[p].l].v) return kth(t[p].l, l, mid, k); 1047 | else return kth(t[p].r, mid + 1, r, k - t[t[p].l].v); 1048 | } 1049 | } -------------------------------------------------------------------------------- /组合.cpp: -------------------------------------------------------------------------------- 1 | int inline power(int a, int b) { 2 | int res = 1; 3 | while (b) { 4 | if (b & 1) res = (LL)res * a % P; 5 | a = (LL)a * a % P; 6 | b >>= 1; 7 | } 8 | return res; 9 | } 10 | 11 | void inline add(int &x, int y) { 12 | x += y; 13 | if (x >= P) x -= P; 14 | } 15 | 16 | void inline del(int &x, int y) { 17 | x -= y; 18 | if (x < 0) x += P; 19 | } 20 | 21 | 22 | void inline preInv(int n) { 23 | inv[1] = 1; 24 | for (int i = 2; i <= n; i++) 25 | inv[i] = ((LL)P - P / i) * inv[P % i] % P; 26 | } 27 | 28 | int fact[N], infact[N]; 29 | 30 | void inline factPrework(int n) { 31 | fact[0] = infact[0] = 1; 32 | for (int i = 1; i <= n; i++) fact[i] = (LL)fact[i - 1] * i % P; 33 | infact[n] = power(fact[n], P - 2); 34 | for (int i = n - 1; i; i--) infact[i] = infact[i + 1] * (i + 1ll) % P; 35 | } 36 | 37 | int inline C(int a, int b) { 38 | if (a < b || a < 0 || b < 0) return 0; 39 | return (LL)fact[a] * infact[b] % P * infact[a - b] % P; 40 | } 41 | 42 | int lucas(int a, int b) { 43 | if (a < P) return C(a, b); 44 | return (LL)C(a % P, b % P) * lucas(a / P, b / P) % P; 45 | } 46 | -------------------------------------------------------------------------------- /联合省选2022讲评.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DMoRanSky/cp-template/bed339f13fd83ff3d917077ebd32a92c66dc6f3c/联合省选2022讲评.pdf -------------------------------------------------------------------------------- /计算几何.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | const double eps = 1e-4; 4 | 5 | 6 | typedef pair PDD; 7 | 8 | int inline cmp(double x, double y) { 9 | if (fabs(x - y) < eps) return 0; 10 | return x < y ? -1 : 1; 11 | } 12 | 13 | double inline cross(PDD a, PDD b) { return a.fi * b.se - a.se * b.fi; } 14 | PDD operator - (const PDD &a, const PDD &b) { return make_pair(a.fi - b.fi, a.se - b.se); } 15 | PDD operator + (const PDD &a, const PDD &b) { return make_pair(a.fi+ b.fi, a.se+ b.se); } 16 | PDD operator / (const PDD &a, double b) { return make_pair(a.fi / b, a.se / b); } 17 | PDD operator * (const PDD &a, double b) { return make_pair(a.fi * b, a.se * b); } 18 | double operator * (PDD a, PDD b) { return a.fi * b.se - a.se * b.fi; } 19 | double inline area(PDD a, PDD b, PDD c) { return cross(b - a, c - a); } 20 | double inline dot(PDD a, PDD b) { return a.fi * b.fi + a.se * b.se; } 21 | double inline len(PDD a) { return sqrt(dot(a, a)); } 22 | double inline project(PDD a, PDD b, PDD c) { return dot(b - a, c - a) / len(b - a); } 23 | double inline dist(PDD a, PDD b) { return sqrt((a.fi - b.fi) * (a.fi - b.fi) + (a.se - b.se) * (a.se - b.se)); } 24 | // 顺时针转 x 25 | PDD inline rotate(PDD a, double x) { return make_pair ( cos(x) * a.fi + sin(x) * a.se, -sin(x) * a.fi + cos(x) * a.se ); } 26 | PDD inline norm(PDD a) { return a / len(a); } 27 | double angle(PDD a, PDD b) { 28 | return acos(dot(a, b) / len(a) / len(b)); 29 | } 30 | int sign(double fi) { 31 | if (fabs(fi) < eps) return 0; 32 | if (fi < 0) return -1; 33 | return 1; 34 | } 35 | 36 | bool segLine(PDD a, PDD b, PDD c, PDD d){//直线ab与线段cd相交 37 | return cross(b - a, c - a) * cross(b - a, d - a) <= 0; 38 | } 39 | 40 | bool segInter(PDD a1, PDD a2, PDD b1, PDD b2) { 41 | double c1 = cross(a2 - a1, b1 - a1), c2 = cross(a2 - a1, b2 - a1); 42 | double c3 = cross(b2 - b1, a2 - b1), c4 = cross(b2 - b1, a1 - b1); 43 | return sign(c1) * sign(c2) <= 0 && sign(c3) * sign(c4) <= 0; 44 | } 45 | 46 | 47 | 48 | // 别用这个 或者要 p + vx, q + wx 49 | 50 | PDD getInter(PDD p, PDD v, PDD q, PDD w) { 51 | PDD u = p - q; 52 | double t = cross(w, u) / cross(v, w); 53 | return make_pair(p.fi + t * v.fi, p.se + t * v.se); 54 | } 55 | 56 | PDD getInter(Line a, Line b) { return getInter(a.s, a.t - a.s, b.s, b.t - b.s); } 57 | 58 | bool inline Right(Line a, Line b, Line c) { 59 | PDD u = getInter(b, c); 60 | return area(a.s, a.t, u) <= 0; 61 | } 62 | 63 | // 点到线段距离 64 | 65 | double getD(PDD a, PDD u, PDD v) { 66 | double w = min(dis(a, u), dis(a, v)); 67 | double c = dot(a - u, v - u); 68 | double t = dis(u, v); 69 | c /= t; 70 | if (cmp(c, 0) >= 0 && cmp(c, t) <= 0) { 71 | PDD v1 = v - u, v2 = a - u; 72 | w = cross(v1, v2) / len(v1); 73 | } 74 | return fabs(w); 75 | } 76 | 77 | 78 | struct Line{ 79 | PDD s, t; 80 | int id; 81 | } e[N]; 82 | // 半平面交 83 | PDD vec(Line x) { return x.t - x.s; } 84 | bool isPara(Line x, Line y){return fabs(vec(x) * vec(y)) < eps;}//判断线平行 85 | bool paraS(Line a, Line b) { return isPara(a, b) && dot(vec(a), vec(b)) > 0; } // 射线同向 86 | int half(PDD x){return x.se < 0 || (x.se == 0 && x.fi <= 0); } 87 | bool cmp(PDD a, PDD b) { return half(a) == half(b) ? cross(a, b) > 0 : half(b); } 88 | bool cmp2 (const Line &a, const Line &b) { 89 | if (paraS(a, b)) return area(a.s, a.t, b.t) < 0; 90 | return cmp(vec(a), vec(b)); 91 | } 92 | vector HPI(vector a) { 93 | int n = a.size(); 94 | for (int i = 1; i <= n; i++) e[i] = a[i - 1]; 95 | sort(e + 1, e + 1 + n, cmp2); 96 | int hh = 0, tt = -1; 97 | for (int i = 1; i <= n; i++) { 98 | if (i && paraS(e[i], e[i - 1])) continue; 99 | while (hh < tt && Right(e[i], e[q[tt - 1]], e[q[tt]])) tt--; 100 | while (hh < tt && Right(e[i], e[q[hh]], e[q[hh + 1]])) hh++; 101 | q[++tt] = i; 102 | } 103 | while (hh < tt && Right(e[q[hh]], e[q[tt - 1]], e[q[tt]])) tt--; 104 | while (hh < tt && Right(e[q[tt]], e[q[hh]], e[q[hh + 1]])) hh++; 105 | q[++tt] = q[hh]; 106 | if (tt - hh <= 2) return {}; 107 | vector ret; 108 | for (int i = hh; i < tt; i++) 109 | ret.pb(getInter(e[q[i]], e[q[i + 1]])); 110 | return ret; 111 | } 112 | // 最小圆覆盖 113 | 114 | Point inline getCircle(Point a, Point b, Point c) { 115 | return Inter((a + b) / 2, rotate(b - a, PI / 2), (a + c) / 2, rotate(c - a, PI / 2)); 116 | } 117 | 118 | 119 | void inline minCircle(PDD a[]) { 120 | random_shuffle(a + 1, a + 1 + n); 121 | double r = 0; Point u = a[1]; 122 | for (int i = 2; i <= n; i++) { 123 | if (cmp(r, len(u - a[i])) == -1) { 124 | r = 0, u = a[i]; 125 | for (int j = 1; j < i; j++) { 126 | if (cmp(r, len(u - a[j])) == -1) { 127 | r = len(a[i] - a[j]) / 2, u = (a[i] + a[j]) / 2; 128 | for (int k = 1; k < j; k++) { 129 | if (cmp(r, len(u - a[k])) == -1) { 130 | u = getCircle(a[i], a[j], a[k]), r = len(a[i] - u); 131 | } 132 | } 133 | } 134 | } 135 | } 136 | } 137 | } 138 | 139 | 140 | // 自适应辛普森积分 141 | double inline f(double fi) { 142 | return ?; 143 | } 144 | double inline s(double l, double r) { 145 | double mid = (l + r) / 2; 146 | return (r - l) * (f(l) + 4 * f(mid) + f(r)) / 6; 147 | } 148 | 149 | double inline asr(double l, double r) { 150 | double mid = (l + r) / 2, v = s(l, r); 151 | double a = s(l, mid), b = s(mid, r); 152 | if (fabs(a + b - v) < eps) return v; 153 | else return asr(l, mid) + asr(mid, r); 154 | } 155 | 156 | 157 | 158 | // PII andrew + mincowf 159 | 160 | LL operator * (PII a, PII b) { 161 | return (LL)a.fi * b.se - (LL)a.se * b.fi; 162 | } 163 | 164 | PII operator + (PII a, PII b) { 165 | return mp(a.fi + b.fi, a.se + b.se); 166 | } 167 | 168 | PII operator - (PII a, PII b) { 169 | return mp(a.fi - b.fi, a.se - b.se); 170 | } 171 | 172 | LL dot (PII a, PII b) { 173 | return (LL)a.fi * a.se + (LL)b.fi * b.se; 174 | } 175 | 176 | vector inline andrew(vector a) { 177 | int n = a.size(); 178 | top = 0; 179 | sort(a.begin(), a.end()); 180 | for (int i = 0; i < n; i++) { 181 | while (top > 1 && (a[i] - a[s[top - 1]]) * (a[s[top]] - a[s[top - 1]]) > 0) { 182 | vis[s[top--]] = 0; 183 | } 184 | vis[i] = 1, s[++top] = i; 185 | } 186 | vis[0] = 0; 187 | for (int i = n - 1; i >= 0; i--) { 188 | if (!vis[i]) { 189 | while (top > 1 && (a[i] - a[s[top - 1]]) * (a[s[top]] - a[s[top - 1]]) > 0) 190 | vis[s[top--]] = 0; 191 | vis[i] = 1, s[++top] = i; 192 | } 193 | } 194 | --top; 195 | vector ret; 196 | for (int i = 1; i <= top; i++) ret.pb(a[s[i]]); 197 | for (int i = 0; i < n; i++) vis[i] = 0; 198 | return ret; 199 | } 200 | 201 | // 有 202 | 203 | vector calc(vector a, vector b) { 204 | vector c; 205 | c.pb(a[0] + b[0]); 206 | vector dx, dy; 207 | for (int i = 1; i < a.size(); i++) dx.pb(a[i] - a[i - 1]); 208 | dx.pb(a[0] - a.back()); 209 | for (int i = 1; i < b.size(); i++) dy.pb(b[i] - b[i - 1]); 210 | dy.pb(b[0] - b.back()); 211 | int i = 0, j = 0; 212 | while (i < dx.size() && j < dy.size()) { 213 | if (dx[i] * dy[j] > 0) 214 | c.pb(c.back() + dx[i++]); 215 | else if (dx[i] * dy[j] == 0 && c.size() > 1) { 216 | // 共线放一起不然是错的!!!! 217 | if (dot(c.back() - c[c.size() - 2], dx[i]) > 0) 218 | c.pb(c.back() + dx[i++]); 219 | else c.pb(c.back() + dy[j++]); 220 | } else { 221 | c.pb(c.back() + dy[j++]); 222 | } 223 | } 224 | while (i < dx.size()) c.pb(c.back() + dx[i++]); 225 | while (j < dy.size()) c.pb(c.back() + dy[j++]); 226 | assert(c.back() == c[0]); 227 | c.pop_back(); 228 | return c; 229 | } 230 | 231 | 232 | 233 | // 凸包面积 234 | 235 | double area(vector a) { 236 | int n = a.size(); 237 | double ret = 0; 238 | for (int i = 0; i < n; i++) { 239 | ret += cross(a[i], a[(i + 1) % n]); 240 | } 241 | return fabs(ret / 2); 242 | } 243 | 244 | 245 | // 动态凸包 246 | 247 | struct Hull { 248 | SI su, sd; 249 | bool inline query(SI &s, PII u, int o) { 250 | SIT l = s.upper_bound(u), r = s.lower_bound(u); 251 | if (r == s.end() || l == s.begin()) return false; 252 | l--; 253 | return cross(*l, u, *r) * o <= 0; 254 | } 255 | void inline insert(SI &s, PII u, int o) { 256 | if (query(s, u, o)) return; 257 | SIT it = s.insert(u).first; 258 | while (1) { 259 | SIT mid = it; 260 | if (mid == s.begin()) break; --mid; 261 | SIT l = mid; 262 | if (l == s.begin()) break; --l; 263 | if (cross(*l, *mid, u) * o >= 0) break; 264 | s.erase(mid); 265 | } 266 | while (1) { 267 | SIT mid = it; ++mid; 268 | if (mid == s.end()) break; 269 | SIT r = mid; ++r; 270 | if (r == s.end()) break; 271 | if (cross(u, *mid, *r) * o >= 0) break; 272 | s.erase(mid); 273 | } 274 | } 275 | void inline ins(PII u) { 276 | insert(su, u, 1), insert(sd, u, -1); 277 | } 278 | 279 | // 0 外面 : 1 线上 : 2 里面 280 | int inline chk(PII u) { 281 | bool in = query(su, u, 1) && query(sd, u, -1); 282 | if (in) { 283 | if (query(su, u, -1)) return 1; 284 | if (query(sd, u, 1)) return 1; 285 | return 2; 286 | } 287 | return 0; 288 | } 289 | } t; 290 | --------------------------------------------------------------------------------