找回密码
 注册
查看: 18|回复: 0

c语言算法填写规范总结来自互联网

[复制链接]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
发表于 2025-3-21 10:23:44 | 显示全部楼层 |阅读模式
算法 {算法代码模板,算法模板编写规范}% A# x1 C& I4 u. S- ~  a! h
supimoTemplate.cpp
" B( N# c- q& d+ a代码* z5 _. Z( |0 Q* d2 k% ~! ~) R* a
#define  ___SUPIMOenvir_  y0 h7 c; F; n9 `* l3 l

. u- f3 |8 c# f#include <bits/stdc++.h>
, E! }, q) m2 e8 y7 ^# {using namespace ::std;7 c7 a7 z/ p! Q: r, |+ @1 W1 H/ E& n

- m6 Y+ t2 R; x#ifdef  ___SUPIMOenvir_; g8 M2 Z7 M+ [  a$ t( `# K
    #include "supimoDebug.hpp"% {# w2 a" h! |& a8 x
#else
- f0 d3 L" Y, k4 a9 H0 L: Q    #define  TOstringITEMS_( ...)  ""% D. o- r4 C  M5 k3 |
    #define  DE_( ...)
3 O* d: _7 v" ~8 I5 t    #define  ASSERTcustom_( _op, ...)   assert(_op)4 T2 e( X4 c/ ^% j( [  r
    #define  ASSERTsystem_( _op, ...)   assert(_op)$ m5 ?1 ?$ `* `9 j
#endif, [+ @" ?6 j$ p! a
; n8 }& Y1 _+ S
#define  ASSERTregion_( ...)  __VA_ARGS__
" y$ m$ G( i0 q1 {- K#define  ASSERTsentence_( ...)6 t+ j; M7 t. d0 l8 Q
#define  EXIT_  std::cerr<< "\nExit(2267): Line("<< __LINE__<< ")\n";  std::exit(2267);0 C6 T5 c7 _2 b$ f. k
#define  EXITcounter_( _max)  { static int cont = 0; ++ cont; if( cont == _max){ string str = "Exit_Counter(" + std::to_string(_max) + ")"; DE_(str); EXIT_;}}
, z; W  u& |3 E; l5 [#define  FOR_( _i, _l, _r)  for( int _i=int(_l); _i<=int(_r); ++_i)
4 \$ L3 R" N2 b) C. _5 ^#define  FORrev_( _i, _l, _r)  for( int _i=int(_l); _i>=int(_r); --_i)
4 o9 B" c6 R% [
( [+ d( p% o& ~, m* {) i- f8 s* j$ Pusing Int64_ = long long;
# d: g  w: M+ A( @* J/ z5 b+ m: e# D. a* ]3 V+ \, h, V5 [+ T

, a. m1 b0 \% f  }& Nvoid ___Solve_oneTest(){
: E: \8 C# |$ K, i. i}
4 _3 I  Y9 W( ?- ~1 hvoid ___GlobalInitialze(){
* q* P- I- q3 U: z! w}
9 y5 n5 M: x0 y/ J9 p2 w% X/ vint main(){$ a! b9 p; a$ k6 z
    std::ios::sync_with_stdio(0);  std::cin.tie(0);2 T/ y+ f9 A% C8 C! @$ g+ K
    std::cerr.setf( std::ios::fixed);  std::cerr.precision( 9);
, u( e6 N. E$ }* g. S2 y    std::cout.setf( std::ios::fixed);  std::cout.precision( 9);
1 |! B3 ?) M. t& ?  g8 a1 p
1 K) y; b4 P2 p. I4 b' F: o    auto ___Solve = [](){ // Problem-Input: ?4 p! F! f9 D2 J& F4 W; U
        constexpr char MODEisSINGLE = 1;
3 S# T1 `) R$ I9 O        int testsCount;
$ G+ {: C, ^' S. ?$ U  B        if( MODEisSINGLE){ testsCount = 1;} else{ cin>> testsCount;}
8 e7 o- E0 O6 X1 X4 F% J. i" ^! e        for( int id = 0; id < testsCount; ++id){
) r$ t  n3 P( i0 I5 j            if( id == 0){ ___GlobalInitialze();}
, m& ?# \5 u4 X$ \2 k8 D. R7 s            ___Solve_oneTest();
; i8 s+ M) _7 z. n0 M        }! Z- Z1 `: Q( }# K1 L+ h2 N3 r
    };; d) [: [( }! p3 z$ E
#ifdef  ___SUPIMOenvir_( V1 k. w8 S# u
    while( 1){0 b$ A  R( v9 D4 h  Y
        std::string flag;  std::cin>> flag;  ASSERTsystem_( flag.substr( 0, 10) == "#___Input[", flag);9 {7 P4 R9 |8 z
        flag.replace( 4, 2, "Out");
; f% Z4 V# y1 y        std::cout<< "    "<< flag<< "\n";  std::cerr<< "    "<< flag<< "\n";
1 }/ a2 c0 m: [/ \+ G        if( flag == "#___Output[-1]#"){ break;}
( X' j* _! `/ u! x//        int timeStart = std::clock();
1 p% o1 l% `& ^8 Q" d        ___Solve();  _6 V: ~+ F% E9 m5 {% K0 U
        std::cout<< "\n";  std::cerr<< "\n";
% f# i0 {7 i: H# l3 m( L+ t  F8 y//        std::cout<< "TimeElapsed: "<< std::clock() - timeStart<< "\n";
' C: U) C# e# ^% l& J9 ?    }8 q# ~8 Z8 ^0 J8 c
#else
3 v( a' k, U- Z" w% }) }) j3 `    ___Solve();
4 |: y/ c. r1 Q8 c6 B#endif
0 ?0 Q# {7 T5 ]0 }" [; l
# j: h( k0 A; S: Y/ _    return 0;
' P% v( q* A' b2 R1 y* _+ }}
: D7 e1 B6 B1 a5 R* n6 C17 `; o( }3 r. R7 X8 S: Y
2( d: A$ _1 U2 Y3 x& Q
3
, z* f' C# I  u: _( |; K4
+ O- g. J& |. ?& w" _5  G: a5 g" t+ g1 W6 @- H) ^
67 L  i$ n& \0 v
7
$ s4 n5 T4 r0 M  H$ q$ m8
: }) v3 \$ w- a, G% R7 U: g9
1 f5 C& Z3 B  C! t9 {$ G0 ~- o10
8 f! {+ T  {3 |$ @118 M% F2 [9 j/ k% E7 E: d
12+ l4 X  K2 l  _, U
13
( Q  M& g; m1 h: u% r! `* T% H( t1 Z# l14
3 v* b9 k8 e  s# q152 z$ b. ]' h/ h1 J" O
16
/ [4 P. }2 L/ Y+ a; |17
/ K6 G- q. N: C7 A18
9 v: Q: h1 c& a* @' g1 K6 _19
  d5 }" u2 n3 S8 f( v# w9 j202 m7 N1 N5 e0 c0 e; B
21
  h& x+ r' T8 ^. a+ K" `! R22
+ p$ J/ K) Q# t; j. P" l23
) V! I' R, p1 M$ b24
# g( x$ L" z5 {6 Q2 F# Y25- n3 @2 f2 `6 u7 D2 Q  K5 ?( x
268 ^1 p- F% b, i6 o1 H! p
27
$ a) D- N0 j8 c/ c6 u5 `28! A- G7 a" L9 N( b
29
& }3 M9 {# u& M6 t! ~! z30
+ g. f- ~$ i3 p0 z! N4 K31- H# M+ G6 D0 R* G+ t' [# K+ C
32' \% e8 c* C+ u4 K: e
33& d$ ^& A. b0 I( u: a
34
- f1 h. G# T+ j3 L9 T+ }2 f5 @  v351 w9 l9 }! Y: u) f. d" l
36; }' N% n. }; g) w( |
37
# r6 e+ @0 `$ {0 I, o, ~# [. f38* w0 r! v% E, T- x8 x% k, ]
39
- L1 t9 O5 C! ?; o: ^, o406 i) R+ _( `: G6 T! f9 u
41+ H" Z! v9 @/ v. Q; T/ f
42
, J. a7 |, @) ^7 O/ K% l' S43- z) \# V" e. i* a! H$ e/ D
44
! N0 G- v/ G) @* {1 V7 Z" U459 Y- h% h9 }- L' l! U) f# |
46* V7 f5 B8 G, F( a- r! B3 @! D
47* L- n5 f) w! @
481 ^  G& l5 \* q. V; x6 t1 Y: o
49: D9 J1 n. Q# P& P6 f
50
, Q4 ]8 A! x+ t0 C4 j! k8 m51
  g# V( r1 v: S( ]+ G523 P5 A! |8 p0 `. G% B( t, t
53+ h3 p1 ?. V" _0 S+ r; n6 ]/ e) q
54$ a$ W# |$ q; G! ?) [2 x( P0 _
55( t$ v9 f& ]5 g# n' [2 @
56
& S+ v# k  n- u. c0 f2 f) }578 ?; J" ^" Y1 s: k
58
* ]5 ]+ r- J- [% f6 D59: Y7 W+ V7 d/ F/ _( C
supimoDebug.hpp: _5 B" Q% w7 W7 z2 Z& [
代码
7 b/ g0 g5 a2 U- _0 }, R" q: P  D#include <bits/stdc++.h>9 T. a3 r( H6 J, z+ w' C; E
! @$ n! I, e  @' }/ f
#define  VARSandLOCATION_( ...)  std::string(std::string("{File: ")+ __FILE__+ ", Line: "+ std::to_string(__LINE__)+ ", VarName: ["+ #__VA_ARGS__+ "]}")
: V: o9 @2 w  F! s. R+ ~#define  TOstringITEMS_( ...)  ___DEBUG_::ToString_Items( __VA_ARGS__)8 F, D0 k' B( _6 y  J# d
#define  DE_( ...)  std::cerr<< TOstringITEMS_( __VA_ARGS__)<< "    "<< VARSandLOCATION_(__VA__ARGS__)<< "\n"
  W0 W' V$ ~3 h3 z) V/ O! j#define  ASSERTcustom_( _op, ...)   if( !bool(_op)){ std::cerr<<"Assertion_Failed(Custom): ["<< #_op<< "]    {Hint: ["<< TOstringITEMS_( __VA_ARGS__)<< "]("<< #__VA_ARGS__<< ");  Line: "<< __LINE__<< "}";  std::exit(2267);}
: d. ~1 X0 s# b/ u1 A  r#define  ASSERTsystem_( _op, ...)   if( !bool(_op)){ std::cerr<<"Assertion_Failed(System): ["<< #_op<< "]    {Hint: ["<< TOstringITEMS_( __VA_ARGS__)<< "]("<< #__VA_ARGS__<< ");  Line: "<< __LINE__<< "}";  std::exit(2267);}9 b; y: R9 N4 t, e) U1 x4 i6 d# _
; j5 X7 @) I) Y9 W1 m, P4 N
namespace ___DEBUG_ {
# _2 g, C* C( ~2 I+ F+ v    //>> 所谓`Container`是指 可以通过`for( auto i : S)`来进行遍历的;
  R! R" e% p( L1 U7 h    template< class _t> struct __IsContainer_Unwrap : std::false_type{};1 m, B; A% k  I' x
    template< class _t> struct __IsContainer_Unwrap<std::vector<_t> > : std::true_type{};
5 J$ K# s2 {# e' R0 [) o* y    template< class _t> struct __IsContainer_Unwrap<std::set<_t> > : std::true_type{};5 U! h0 \' J9 q) N$ _% n
    template< class _t> struct __IsContainer_Unwrap<std::unordered_set<_t> > : std::true_type{};; f  k# d% \7 G
    template< class _t> struct __IsContainer_Unwrap<std::multiset<_t> > : std::true_type{};
* \) N5 N7 ?: ^8 Y    template< class _t> struct __IsContainer_Unwrap<std::unordered_multiset<_t> > : std::true_type{};& ?5 j/ K3 j6 p( J
    template< class _t0, class _t1> struct __IsContainer_Unwrap<std::map<_t0,_t1> > : std::true_type{};2 H# o7 v1 W  b
    template< class _t0, class _t1> struct __IsContainer_Unwrap<std::unordered_map<_t0,_t1> > : std::true_type{};
3 L9 l9 W  I9 a1 {- k) A    template< class _t0, int _t1> struct __IsContainer_Unwrap< _t0[_t1] > : std::true_type{};
* T7 J, l4 R$ a5 L3 `    template< int _t1> struct __IsContainer_Unwrap< char[_t1] > : std::false_type{}; // 特判, 字符串常量"..."不属于容器;
5 r& t( f+ n5 x: a3 A    template< class _t> struct IsContainer : __IsContainer_Unwrap<std::remove_const_t<std::remove_reference_t<_t> > >{}; // 不能用`decay` 否则`T[N]`就退化为`T*`了;
2 v; K  T( a, u/ G  v& D+ j# Q' d9 S  }0 P9 e2 E
    template< class _t> struct __IsPair_Unwrap : std::false_type{};
3 _; S2 ]; i, F* G& \    template< class _t0, class _t1> struct __IsPair_Unwrap< std::pair<_t0,_t1> > : std::true_type{};" L6 W) e7 Q0 [/ `+ e9 G3 h, @
    template< class _T> struct IsPair : __IsPair_Unwrap< std::decay_t<_T> >{};% b' V# C% y- \! X' z* N  n4 C
6 e* y$ k: E" ]- p5 o/ L
    template< class _t> struct __IsStack_Unwrap : std::false_type{};
) l2 }) P) Y  ]2 G# c* [; O$ f  U7 t& W    template< class _t> struct __IsStack_Unwrap< std::stack<_t> > : std::true_type{};
2 K9 y3 s1 x4 O+ |' b    template< class _T> struct IsStack : __IsStack_Unwrap< std::decay_t<_T> >{};' C/ J" E; b3 r

, b4 B) p  M! Q/ \1 a. S/ U+ Z, O    template< class _t> struct __IsQueue_Unwrap : std::false_type{};5 c: f" z, D8 K, @/ U5 L, O
    template< class _t> struct __IsQueue_Unwrap< std::queue<_t> > : std::true_type{};
) ]  W# I" K$ ?    template< class _T> struct IsQueue : __IsQueue_Unwrap< std::decay_t<_T> >{};9 l; G! _' }2 q! j* I1 {# I" U/ E7 Z

+ W6 L$ h: D+ W) S! v( _( g    template< class _t> struct __IsDeque_Unwrap : std::false_type{};
& b4 g: `& E% c  O( q3 X, P    template< class _t> struct __IsDeque_Unwrap< std::deque<_t> > : std::true_type{};% O' A5 b1 A. T& {
    template< class _T> struct IsDeque : __IsDeque_Unwrap< std::decay_t<_T> >{};
7 Q- X0 a$ p5 }) q& Q/ Z( l
& P$ J% _( K* M, ?8 D) U8 D4 [; q' P    template< class _T> std::string ToString( _T const&);
' v9 o7 q% [$ i- g
/ Y% x1 c; I; H/ S# i+ b    template< class _T, int _Check> struct __ToString_Category;
6 l; S! ^/ ^- i; S. z2 W    template< class _T> struct __ToString_Category<_T, 0>{ // Single
; P" M' k3 r8 R5 \/ }2 m    template< class _t> static std::string TOstring( _t const& _v){* N  n' A3 ?! ?+ t* s* g
        std::ostringstream ANS; ANS.precision( std::cout.precision()); ANS.setf(std::cout.flags()); ANS<<_v;
( _$ G4 h6 L  I& c( Q; H        return ANS.str();
" A' m$ C0 R% L! W* N7 x    }
* h2 C7 @+ Q5 ?& E8 F    static std::string TOstring( unsigned __int128 const& _v){ auto v = _v; std::string ANS; if(v==0){ ANS="0";} else{ for(;v!=0;v/=10){ ANS+=('0'+v%10);}  std::reverse(ANS.begin(), ANS.end());}  return ANS;}
6 v" T- o( p/ ~0 w% ?; k    static std::string TOstring( __int128 const& _v){ std::string ANS; auto v = _v; if(v==0){ ANS="0";} else{ if(v<0){ ANS+="-"; v=-v;}  for(;v!=0;v/=10){ ANS+=('0'+(v%10));}  std::reverse(ANS.begin()+(ANS[0]=='-'?1:0), ANS.end());}  return ANS;}
5 U5 i4 I( b8 F3 \/ e    static std::string TOstring( bool const& _b){ return (_b?"1":"0");}
# V! z, u- F% ?; Z7 w- O9 d    static std::string TOstring( char const& _a){3 \9 Q: |5 h0 V/ F- f
        if(_a==0){ return "'\\0'";} // 否则因为她是*结束控制符* 会导致`ostream<<char(0)<<A;`后面的`A`不输出了;
; p/ ]- g6 F* S" G( ~$ r; S        std::string ANS="'?'"; ANS[1]=_a; return ANS;. T4 z7 a* W; `, r  f
    }0 x( W9 N% y( D8 }* o2 p! g
    static std::string TOstring( char const* const& _s){ return std::string(_s);}# a- n5 S- ?7 x
    static std::string TOstring( std::string const& _tt){ std::string ANS="\""; ANS+=_tt; ANS+='\"'; return ANS;}
$ B/ _# a- U- Z0 e" {" Z    };
6 j1 T1 P$ a% F: Y% U( Z! ~    template< class _T> struct __ToString_Category<_T, 1>{ // Container
0 p) Q6 s0 K) l  }# b' k        template< class _t> static std::string TOstring( _t const& _v){8 E; u$ j2 D& C
            std::string ANS="["; bool first=1;
# {5 Q0 y) p- N' W; |* ?5 z2 U8 a            for( auto const& i : _v){ if( 0==first) ANS+=","; if( first) first=0; ANS+=ToString(i);}( Q  M* ^! b. o0 q* A$ @$ f
            ANS+="]";0 s0 n9 F1 u# q! @4 r2 f$ B1 j
            return ANS;
$ ^/ U% j( I8 F7 N        }
/ G% c6 c( Y. E, ~9 `. h    };
1 [( H/ u2 m5 u( r* R6 [5 S- ?  G* a    template< class _T> struct __ToString_Category<_T, 2>{ // Pair
$ s' F' w% p9 ?6 @  H: ^9 y        template< class _t> static std::string TOstring( _t const& _v){ std::string ANS="("; ANS += ToString(_v.first); ANS+=","; ANS+=ToString(_v.second); ANS+=")"; return ANS;}
+ ?4 R/ @- l; u! H4 p8 |    };4 Q" z% Y) |; N" u9 c5 ?3 b
    template< class _T> struct __ToString_Category<_T, 3>{ // Stack
: r1 G% l3 c8 n7 ~) M3 w        template< class _t> static std::string TOstring( _t const& _v){ std::string ANS="Stack(top)[";  auto t = _v;  for( bool first=1; t.empty()==0; t.pop(), first=0){ if(first==0){ ANS+=",";} ANS += ToString(t.top());} ANS+="]"; return ANS;}# v8 X" q% Y& s3 Y: a% w$ M
    };) d  M) {7 t/ F1 j) ?: F
    template< class _T> struct __ToString_Category<_T, 4>{ // Queue
; I6 u/ X4 B# G8 ?+ O        template< class _t> static std::string TOstring( _t const& _v){ std::string ANS="Queue(front)[";  auto t = _v;  for( bool first=1; t.empty()==0; t.pop(), first=0){ if(first==0){ ANS+=",";} ANS += ToString(t.front());} ANS+="]"; return ANS;}
0 w; l: J5 E. n: j. q    };
! t" o$ `0 Z5 {% G$ N2 B3 S- H0 H    template< class _T> struct __ToString_Category<_T, 5>{ // Deque; m$ `. L" _% U! B, l% O
        template< class _t> static std::string TOstring( _t const& _v){ std::string ANS="Deque(front)[";  auto t = _v;  for( bool first=1; t.empty()==0; t.pop_front(), first=0){ if(first==0){ ANS+=",";} ANS += ToString(t.front());} ANS+="]"; return ANS;}- c4 o/ t0 x) F
    };
" l! p8 d4 \# i( J# F+ \' B! M8 P! [
    template< class _t> struct __ToString : __ToString_Category<_t, (IsContainer<_t>::value ? 1:(IsPair<_t>::value ? 2:(IsStack<_t>::value ? 3:(IsQueue<_t>::value ? 4:(IsDeque<_t>::value ? 5:0)))))>{};
. B+ w* g% [/ F8 d' G0 U8 x, M! L
    template< class _t> std::string ToString( _t const& _v){ return __ToString<_t>::TOstring(_v);}
# S  y: J5 x- v8 {0 W6 S
, P/ u/ ?+ q% G3 r    template< class... _H_> std::string ToString_Items( _H_ const&...){ return "";}3 \2 w4 z  L; K0 M
    template< class _H_> std::string ToString_Items( _H_ const& _h){ return ToString(_h);}. N) S# V8 P. ]8 {/ ^0 m; \. d* o
    template< class _H_, class... _T_> std::string ToString_Items( _H_ const& _h, _T_ const&... _t){ std::string ANS; ANS+=ToString( _h); ANS+=", "; ANS+=ToString_Items( _t...); return ANS;}
; j/ w7 D1 n  b9 U  r1 J- u! @2 G}) P6 ~7 [, h5 ~& b: q9 m9 k
4 n7 f6 C. J! z. F
1
  r" D$ g3 X, p* A1 _1 Q; K3 k6 H! I2' S+ s2 y1 R% o+ e$ p; Z
3  n4 ]9 ?) @/ g/ V
44 C+ z9 N7 e7 O9 }! ^
5
5 w) ?* f, s- S) V3 [  j6: j8 K/ S$ |8 E  }7 e" ~
7
1 I  b* h; D1 w' @0 t# D% N8
  f! J8 k5 v+ p! n9
( o: M, O. Y8 n% T5 A7 b10
, g! I$ A+ t  S6 t/ d! a  Q0 f11
# T2 s, _# P, H% Q0 [( j12$ d1 I& `5 G$ g8 w7 g5 [' Q
13! G+ f1 B3 b. _. {5 z, I
143 X* K) F$ b7 k# a% X' v( `0 ?
15/ Z# Y$ S# y( E5 E1 S" \0 |/ Q
16/ W- {$ e5 u) z0 O
173 S4 G3 a. {/ G' b) h. p
18! H5 W) \) `# P$ p( o) Y, k
199 Z, d5 j4 @1 k# u* M3 w* S. }
20: m! I) @( f3 c
21
8 q, }! W# I" w7 {' X: L$ y4 i22
  g$ C9 `; L) w23
# L! ?" y. g' Z- y1 A. t3 D8 }( Z, h: P; n24
; x: U# F* p  X4 z1 j251 A+ ^8 m# a) ]3 n! ?; P1 u/ ^
26
: I: |# s6 K& B) S0 K276 H$ J+ @/ ~# c1 O' k. e' d
280 Y, \. {, {* o* k  n
29
- V- R' @( I* _( b# e$ q30
: `& [8 i. i# _: R( ]4 U31
. I3 Y8 T8 y9 B& A0 G! a; P321 B8 F1 i  n) l
33
. x, ~! B( T) {5 w' P34
, [* S; b0 s- `$ e; [3 Z" o35: X3 V3 Y  B+ M2 `8 ]! L) A* M
36' i' [9 w1 K( ?' `0 e! P
37/ @6 n" I" S, q, y4 @& W$ N" H
38! a* g6 `  M& N, j' U7 z
39
) U3 W* m/ A$ f5 W7 l& C- _40& E! R- H1 A* {1 a8 t
41
3 K+ o: E. k- p7 q) T4 q42
2 h2 f4 C% J% E6 L! H9 b43
; @" R! n% O2 o  u6 T' k& Z44
0 t) O1 C; S* i: J45
$ |4 _0 [0 s/ B* {$ w46
! i" w+ V, H. \1 A- |/ {476 o. V& Y5 Q, t9 n8 n1 b: u
483 [6 n0 z5 |$ H% @* F
49
2 f) z# p) N2 L# t' u3 b- l$ ?50' E( }1 r; a: v% O# C; o+ Z
51
/ x- N- w: t8 w9 q2 _7 W8 E% H52
+ K# n7 L* z. p53
! W7 ~* e) X1 d7 U3 G- u540 D# G: `+ \# B4 w' h9 {
55
; i8 Y' z7 I. Q) w# J5 N56
% A  x$ M) E$ k$ j' x% T57
9 ~+ Y2 Q# F7 v  {) t/ ?58
2 O! K" _( W; T( V% j& }% Z59
1 |5 G& [9 O% _3 B4 S- ^' G( h60
) F+ s1 r: p' \: ^; b# m; p610 B: r  h: t+ A) w$ |3 c2 v8 b
62
8 M# q5 ~# W9 W/ P63% w+ e" s0 J9 I) i* i! E+ F
64" b3 V4 z0 W' _" B
657 T- |3 D% B2 z5 y7 W
66! C3 y8 F5 K: W8 t- d7 h( _
67
3 u# E4 Q' H# Z- c0 E681 B* ~- }: [: A# z2 P; X) _
69- L# V' h3 \* z" e
70, I$ p' y) C/ C/ O/ w8 Z; k  E9 l
71% O, i7 f3 x. v2 e% U0 U: b3 K7 w
72: a+ `8 C. i1 Z
733 q9 ?# U; i. p0 U7 O
74! S, ^- R# [9 U' _- K& q% X; t; ?0 e; i
75
7 K9 b1 i3 h8 z  x9 z) N76
% t; c, g; {1 O1 e, R  M9 `. U) T: E77
1 t! b0 _( e% [) ]7 E! U" X78
# l! L/ |" l" n, p9 _6 Y79
( \$ x1 X7 ^7 A# f9 g: k& h$ e: n80  \3 q5 T# F# t& ]& x  N. z5 R* S
81
8 `0 h! Y# k, O82: C* A. ~, U9 |# q- K0 K& O% U
83
5 a2 [9 O1 m1 B. c84
  X' V* `3 u  B85) c: U# B! z7 b9 g
86
- `- B8 {! m/ \; R6 l3 i性质
; k* Q! K7 W' t. j# B. ]- F! D#TOstringITEMS_#
0 j# N* h  W) |; f这个宏 是为了: 对类进行输出时 可以直接_cout<< TOstringITEMS_(成员变量...);
8 P6 N/ ~, L5 B4 h$ A4 w  e你可能认为, 直接_cout<< ___Debug_::ToStringItems(...)不就行了?7 ]8 [: e# [2 s- @- v6 `$ z
. 错误, 因为在最终文件里 是看不见___Debug_的, 所以写成一个宏 在最终文件里 #define TOstringITEMS_ "";0 Q: `  R, S; k7 T

( H! X2 q- S) W, h# n% S8 l笔记3 b; V* T' [+ t9 {& U  \
#以前的debug.hpp#4 W% h7 }& E" p1 K7 r. q4 n4 i0 ~
. O- v  _; x. g8 V3 o; ?! {
//{ omipusDebug.hpp' O, L" s. L" ?* q
#include <bits/stdc++.h>0 |! K0 N# v( M8 t* D. m' T
* E2 f' m# _0 ^8 R
#define  TOstringITEMS_( ...)  ___DEBUG_::ToString_Items( __VA_ARGS__)
; A/ K2 E( O8 a/ L+ A#define  DE_( ...)  std::cerr<< TOstringITEMS_( __VA_ARGS__)<< "    "<< "{"<< "Line: "<< std::to_string(__LINE__)<< ", Var: ["<< (#__VA_ARGS__)<< "]"<< "}"<< "\n"
; X7 O2 Z1 ]( w' k! e#define  ASSERT_( _op, ...)   if( !bool(_op)){ std::cerr<<"Assertion: ["<< #_op<< "]    {Info: ["<< TOstringITEMS_( __VA_ARGS__)<< "]("<< #__VA_ARGS__<< ");  Line: "<< __LINE__<< "}";  std::exit(2267);}
+ p% E5 ]: H' G6 L( {$ R+ S( t#define  ASSERTsystem_( _op, ...)   if( !bool(_op)){ std::cerr<<"Assertion(System): ["<< #_op<< "]    {Info: ["<< TOstringITEMS_( __VA_ARGS__)<< "]("<< #__VA_ARGS__<< ");  Line: "<< __LINE__<< "}";  std::exit(2267);}
% H. r4 G) V, h. @% N+ F- ^! {1 q
" ]0 E  L+ y# Onamespace ___DEBUG_ {4 f6 X% V& H5 n6 `  @' i  i6 r
    template< class _t> struct __IsContainer_Unwrap : std::false_type{};  // 所谓`Container`是指 可以通过`for( auto i : S)`来进行遍历的;
" i/ M0 b0 ]9 P8 N5 N    template< class _t> struct __IsContainer_Unwrap<std::vector<_t> > : std::true_type{};6 d3 L8 c$ S7 B6 k7 M4 M: t* L
    template< class _t> struct __IsContainer_Unwrap<std::set<_t> > : std::true_type{};
5 e! f7 @2 w# A- s    template< class _t> struct __IsContainer_Unwrap<std::unordered_set<_t> > : std::true_type{};
2 U+ K7 p: V  d$ \: j    template< class _t> struct __IsContainer_Unwrap<std::multiset<_t> > : std::true_type{};# Z/ h) n1 f1 \7 r; v
    template< class _t> struct __IsContainer_Unwrap<std::unordered_multiset<_t> > : std::true_type{};
" c* h- j: R$ p    template< class _t0, class _t1> struct __IsContainer_Unwrap<std::map<_t0,_t1> > : std::true_type{};/ d5 v5 c8 q3 E1 u) f2 K6 W7 {
    template< class _t0, class _t1> struct __IsContainer_Unwrap<std::unordered_map<_t0,_t1> > : std::true_type{};7 C- ]3 X  J; v  G- j
    template< class _t0, std::size_t _t1> struct __IsContainer_Unwrap< _t0[_t1] > : std::true_type{};! F8 q( x+ E0 G" \
    template< std::size_t _t1> struct __IsContainer_Unwrap< char[_t1] > : std::false_type{}; // 特判, 字符串常量"..."不属于容器;0 M1 x+ d+ ~! m: L# H1 {
    template< class _t, std::size_t _siz> struct __IsContainer_Unwrap<std::array<_t,_siz> > : std::true_type{};* N% k# H" k8 s1 g. e2 U
    template< class _t> struct IsContainer : __IsContainer_Unwrap<std::remove_const_t<std::remove_reference_t<_t> > >{}; // 不能用`decay` 否则`T[N]`就退化为`T*`了;
2 e2 g0 \% v- U5 ^5 e# n1 ^4 D- [% H, P# r# p! h
    template< class _t> struct __IsPair_Unwrap : std::false_type{};
5 n  w, A( ?' t3 U2 a    template< class _t0, class _t1> struct __IsPair_Unwrap< std::pair<_t0,_t1> > : std::true_type{};
! F7 f  t- w! V4 c6 X8 O6 k    template< class _T> struct IsPair : __IsPair_Unwrap< std::decay_t<_T> >{};
: k2 F/ Y& f" n( r! t) Y
9 o  S' W- Q" k8 V    template< class _t> struct __IsStack_Unwrap : std::false_type{};
" M7 B0 E: L* j3 S    template< class _t> struct __IsStack_Unwrap< std::stack<_t> > : std::true_type{};
- s3 S. L" v, ~( R    template< class _T> struct IsStack : __IsStack_Unwrap< std::decay_t<_T> >{};& g+ f" L. W; J! W2 Y
- b8 W. S3 o0 I6 p. ]" W3 A, \1 S
    template< class _t> struct __IsQueue_Unwrap : std::false_type{};
5 n% Y+ X6 z& O' m' Z* @& e! B    template< class _t> struct __IsQueue_Unwrap< std::queue<_t> > : std::true_type{};
2 z, l# h( S- Q* e; g: P- J    template< class _T> struct IsQueue : __IsQueue_Unwrap< std::decay_t<_T> >{};
* b/ d$ g8 X% q- D: o# ]- S1 q8 R/ b; ?, w0 j
    template< class _t> struct __IsDeque_Unwrap : std::false_type{};, W2 v0 A! \; b+ I( Q8 V. [
    template< class _t> struct __IsDeque_Unwrap< std::deque<_t> > : std::true_type{};) v) N2 L- v4 a. b; J& N; a
    template< class _T> struct IsDeque : __IsDeque_Unwrap< std::decay_t<_T> >{};
  S( c; E; U2 z% U8 f, ]. ]( J6 q
; G8 f2 O9 ]2 M, \6 ?    template< class _T> std::string ToString( _T const&);: _% K. y8 s. ?+ c

5 Q* v, a0 \' F2 n    template< class _T, int _Check> struct __ToString_Category;7 e" Y0 C$ \/ b* z: V% I
    template< class _T> struct __ToString_Category<_T, 0>{ // Single
% L: U$ `( r8 z; b' T  |        template< class _t> static std::string TOstring( _t const& _v){9 X: X+ G/ f9 _" {: b7 [0 J
            std::ostringstream ANS; ANS.precision( std::cout.precision()); ANS.setf(std::cout.flags()); ANS<<_v;
0 R& t) [1 w* M# r% g+ s" i# C- L            return ANS.str();- t) ]+ k$ K! b9 t
        }
$ x$ P: i8 L: I& j; `0 x# i        static std::string TOstring( unsigned __int128 const& _v){ auto v = _v; std::string ANS; if(v==0){ ANS="0";} else{ for(;v!=0;v/=10){ ANS+=('0'+v%10);}  std::reverse(ANS.begin(), ANS.end());}  return ANS;}% `: }) z0 D- t% Y0 W1 t7 X
        static std::string TOstring( __int128 const& _v){ std::string ANS; auto v = _v; if(v==0){ ANS="0";} else{ if(v<0){ ANS+="-"; v=-v;}  for(;v!=0;v/=10){ ANS+=('0'+(v%10));}  std::reverse(ANS.begin()+(ANS[0]=='-'?1:0), ANS.end());}  return ANS;}
& F- ^/ @+ c+ P4 u0 f        static std::string TOstring( bool const& _b){ return (_b?"1":"0");}
0 S) [& g: X5 E& M: N$ F6 c        static std::string TOstring( char const& _a){
9 v2 b; ?: f% }4 P$ _# D            std::string ANS="'?'";
5 }! U/ Z& y$ t% w& P# K4 G/ b            ANS.replace( 1, 1, std::to_string(_a));& L) C' S0 Z8 B" u/ w# J4 R# s4 y
            return ANS;
  H& y- q; q. G. X        }1 `7 a, z2 ]- `! a) i
        static std::string TOstring( char const* const& _s){ return TOstring(std::string(_s));}
- p& e8 R) v, v% E8 R        static std::string TOstring( std::string const& _s){ std::string ANS="\""; ANS+=_s; ANS+='\"'; return ANS;}
2 x: \% x- O. T4 F    };
: ^9 ~$ `& \& y. U4 k    template< class _T> struct __ToString_Category<_T, 1>{ // Container: F# w( S* X+ k2 T! C; D( a3 |% {
        template< class _t> static std::string TOstring( _t const& _v){
. j3 \3 ~3 d0 C9 m- J# z- ~            std::string ANS="[";  bool first=1;  for( auto const& i : _v){ if( 0==first) ANS+=","; if( first) first=0; ANS+=ToString(i);}  ANS+="]";, I7 b1 l( J0 r- t0 J
            return ANS;" U* P. f. n- O. n) y" f) ~* X
        }
, ]9 Q7 p2 i, x6 b; U    };
4 G  p" h* r, D4 s% Q9 ]    template< class _T> struct __ToString_Category<_T, 2>{ // Pair
' C& m; z; O; Q  N" {        template< class _t> static std::string TOstring( _t const& _v){ std::string ANS="("; ANS += ToString(_v.first); ANS+=","; ANS+=ToString(_v.second); ANS+=")"; return ANS;}
; P, }2 G. ?  {. i    };
+ r) i% N3 ?$ D( b7 A5 ^    template< class _T> struct __ToString_Category<_T, 3>{ // Stack
( R1 O, M) s2 W/ Z5 j6 O        template< class _t> static std::string TOstring( _t const& _v){ std::string ANS="Stack(top)[";  auto t = _v;  for( bool first=1; t.empty()==0; t.pop(), first=0){ if(first==0){ ANS+=",";} ANS += ToString(t.top());} ANS+="]"; return ANS;}
  N; o6 y) B1 R& u0 H3 I% |# ~    };) A0 Z; N9 h8 P3 u. F! n. r9 \
    template< class _T> struct __ToString_Category<_T, 4>{ // Queue) s+ v4 c' E2 Q2 J8 ^8 r0 @
        template< class _t> static std::string TOstring( _t const& _v){ std::string ANS="Queue(front)[";  auto t = _v;  for( bool first=1; t.empty()==0; t.pop(), first=0){ if(first==0){ ANS+=",";} ANS += ToString(t.front());} ANS+="]"; return ANS;}) z9 P9 z: w5 l5 a
    };
2 `' r' Q, H* k+ q( `2 D4 Y    template< class _T> struct __ToString_Category<_T, 5>{ // Deque
/ m2 S+ ]/ s7 a; I7 c" c        template< class _t> static std::string TOstring( _t const& _v){ std::string ANS="Deque(front)[";  auto t = _v;  for( bool first=1; t.empty()==0; t.pop_front(), first=0){ if(first==0){ ANS+=",";} ANS += ToString(t.front());} ANS+="]"; return ANS;}
, q. y- ?6 [6 g& M    };
) ?, L* k. ]+ S0 v' G0 L7 z. e( I* R& n+ l  i, [( a1 u
    template< class _t> struct __ToString : __ToString_Category<_t, (IsContainer<_t>::value ? 1:(IsPair<_t>::value ? 2:(IsStack<_t>::value ? 3:(IsQueue<_t>::value ? 4:(IsDeque<_t>::value ? 5:0)))))>{};1 ^! R6 v' w8 B2 V9 P8 }( N

  V( J6 N6 x6 A7 J9 F    template< class _t> std::string ToString( _t const& _v){ return __ToString<_t>::TOstring(_v);}8 n. x0 T, E, }; A% z% J
( L5 H- Q- L4 N: h! n
    template< class... _H_> std::string ToString_Items( _H_ const&...){ return "";}
  F: v+ `# m% q7 H" D: N/ i    template< class _H_> std::string ToString_Items( _H_ const& _h){ return ToString(_h);}
$ Y  Z. K5 k% p    template< class _H_, class... _T_> std::string ToString_Items( _H_ const& _h, _T_ const&... _t){ std::string ANS; ANS+=ToString( _h); ANS+=", "; ANS+=ToString_Items( _t...); return ANS;}$ s5 D9 u2 |1 a. G2 \
}6 C; L3 a9 T" \# h+ O1 {
//} omipusDebug.hpp
; s* R4 i& R# c8 K" e  j1
! j7 x- a( b) T/ M. |2
* D7 v; E3 g* l$ C' m% n3: K" k7 Q# X1 N. y5 I( c3 W
4' z5 Q  Z' z/ v
5
. P3 ~. e. Z+ u) V4 Z4 g+ a. ~64 f+ I! g) p3 G; u; v( w! |
7
* E% s! [/ V% a. n. k, n1 C86 ^4 ?' m& o" k/ R$ s. k
9) J: [% }. k. T, f$ J  J" G
10$ P* J" ^  K+ N! Q- z. y# i0 x  ^
11, b4 v8 w0 i% w
12
+ W$ K4 N8 [$ m# c! Q* G13
' B' y5 D: K% g4 _14- X: n5 _* K( C- d! ?4 w
15+ f; u" Q5 d7 P$ A$ R& n- \
16/ k7 z, M& L0 c7 q
17
) p3 b9 F% W8 p3 m. }6 H  q185 T) u% g8 F- p" q' N+ P1 b/ K
19
$ a: L2 O! ~' W6 C: }20
# X, {0 u7 {9 e, }# c21. ~: g& R5 G- F' T
22
9 I1 x- N/ C* |$ ^3 ~  N23
% [1 U( b. C1 Q! O# K$ Z, c# y24
& r' ^+ e% Q' u" R25
* P2 w- Q) U! B$ H26: E+ ]! c# Z7 l9 x1 D5 ~* ^
27
$ r+ ~; F0 {7 e0 G28
6 N& k) p( I3 ^4 }( R/ o29' S+ @7 o7 O6 I/ d2 o: m6 _
30
1 O' I9 A' w( `( k3 y* k31" k7 y" ^% u+ Y! n) H
32
  b  f7 d" C  X5 s  U/ j. S; A33' I7 u/ b/ `4 X0 K: l
34( {, I8 l% L/ |, u6 Z
35
- D; d8 W# G5 l8 D2 C9 D36: C$ b# X2 g1 I; r, p; p
370 I# \0 |7 A4 F
38: e7 \, V) w! T; ^& L: b6 F
391 s+ w# A4 B0 A
40
' H5 W% g, Y% B: g/ L8 ]1 |41
4 h/ |: O. o* X8 |42$ N; A( a! E* y
43
& {- R. a$ ~' p% p440 W5 d) J2 [8 s3 Z3 |; c, q
45
7 L" j4 q7 d, J' l* B; O% _5 P46
( J* S  @5 {4 j* L; s+ M& w47, M, b# T- ?) G& I
48. Q' x- p2 A' R. v
49
- K+ R+ d- O8 g* D3 |50
1 P) t) |# o/ O7 L$ }% P' P6 w51
# u- u2 a$ y0 b' z$ h52
3 O- Z, z, F; P! z' ~- Y2 L" B( v53: @4 W: O7 g% z& ?
54
8 u, m% M0 m: [2 a55( P; F+ k& R8 `) ]: T! ^, J+ w& O2 ?
56% X& r, [+ ~' v  s9 A, N7 Z
575 d, B0 d9 T& O1 ~/ A
58
4 `: Q& k3 ^2 J# q$ P) F5 j& @59
' \0 ^, e( O' @/ X% Q. r0 l0 ~60" W! ~5 ?- o6 D* I: Q% s1 ~% Z
61
! H+ ]/ g, n9 N, [0 K8 s62
7 H! K5 \! j- M+ i: H$ L3 |63, [* g( `. b: b
64
5 }. E6 }" z2 p" c65
1 [2 ^! |( k' n: o6 K. i* k- s/ P66! ~  e0 M# q3 S8 v
67  i( q9 a+ D/ A" n7 z
68: \7 L% ~, @: i; T
69$ a7 I3 g5 s( S$ f$ c; r
70
4 k' D: R" Y: I" t' T( o71& Y! Y2 Y; w( F* `+ J; N' R
72
( x* v. o: T! o/ \! Q$ i732 O' _5 V8 g. ]; m; V
74+ u6 w3 p9 G: O. a6 `8 U/ J; L3 {0 `
75% b6 h) ~7 E- c/ W, M
76
3 T) u6 J' P1 @77
6 K3 p% y* M; S. A2 P- [78/ e/ C5 n( J, `9 r% Y
79
" _: B. s" B& P9 @! D8 v, \800 S- U, X4 f, E0 I
81
  A; w+ |) g9 T: t# C; h823 i0 P& n/ m+ ?$ d, Y+ @
83' k/ T! {- [# r% l. z
84* r7 q( H! @3 ^+ f
85
- ^& j4 C/ {0 |! U3 w算法競賽配置
' S9 w' Z! a( v; UQT_Creator
; w- U4 l2 R* f8 E9 H  Y創建一個控制臺應用, 然後在Pro文件裏 添加CONFIG += c++17 (原來是c++11 修改成17);- C1 L0 \" ^4 b3 A* l: w! m

" W6 K9 j* D6 W  n8 M" L* e7 Z# f6 t對拍文件4 q% g& q  Y8 u
`compare.cpp`7 O! C8 q7 P0 r5 K
% S( U. `. t/ d8 W% [
int main(){
8 E) g8 J* ]( y! u- [+ C    vector< const char *> Init{"build.bat  generate_data",
; a/ s$ O$ j* }3 H' t4 ?3 Z. L* k                              "build.bat  supimo",6 W* |- p& V: r) M) y
                              "build.bat  correct"};1 }7 D1 Y- F- k; W/ P) w
    for( auto order : Init){5 I% Q6 F- V- r$ g5 M
        auto errorCode = system( order);; B( X( R1 M$ @$ p
        if( errorCode != 0){ EXIT_( order, errorCode);}
9 S2 o$ N( g  R+ Z- {4 N4 h+ e4 O    }
3 p' [4 M3 b) w7 h( n+ F8 A, h' S* S! Y$ U6 W) i' k: k
    while( true){$ C% Q, I2 Q4 }" L6 B
        static const char * Ords[] = {"generate_data.exe > data.in",
8 }( x  v* _1 X& q) c                          "supimo.exe < data.in > supimoOutput.txt",% Z" [' h- \2 \+ X5 y3 f; C8 o+ h
                          "correct.exe < data.in > correctOutput.txt",  r. T: i# W5 |0 `
                          "fc supimoOutput.txt correctOutput.txt"};  j7 m; c' a* {/ n
        for( auto order : Ords){
5 |" Y" w$ r) _# ~. D            auto errorCode = system( order);5 k" o9 n+ u9 B# o* m7 l- @; C* n5 s
            if( errorCode != 0){ EXIT_( order, errorCode);}
( y* S" }/ X$ c        }
. ^1 |* Q5 V5 J# A0 z4 n" O! ~9 L        cout<< "SUCC"<< endl;3 }; E% `4 c+ ^+ B2 {; g
    }
$ Y7 K7 X) L+ E2 k6 S0 t( [. d$ ]2 r  x- b
    return 0;
9 y# B" k# @2 @4 ~2 _* t}8 O4 C  p# k) ?9 Q( R- I( w
1
4 j+ t2 z9 w0 Q2
( @! d( }& H9 i/ G% ^33 ?  c3 U/ {" _4 c
4( A+ ]4 F2 [$ p
5+ X% |- c3 M/ l$ R' T
6% {& S8 n, ]; J5 h. J: C$ _
72 r! T! ]6 u( v
8- E& b4 M# q% A7 @
9
1 N9 I+ {/ \4 P0 j# g0 U% v: y% j100 J' r+ t' ?# X3 t' b( J
11
0 t7 v3 R( r8 {! y) i7 G, x126 D" s: @, F4 H( @) X* A/ [$ U' A
13
$ A0 @1 j& {  |( d& u7 l140 d) J3 L* x' e6 Q+ n- b. ?
15
/ F2 x/ v( D- o* @. r16: a5 {  v3 g2 v0 `5 _
17
/ z9 p0 t1 P: B18
: M4 b( Z$ l2 x- S  }0 d193 D% n& C  J# H% L' r" U2 z( O
20) {' r7 g4 f, a2 l
21
" K: f* o0 `; R4 i( ?1 B- w0 r22
8 ^1 {: t9 P9 g( m6 X23$ N, ]: R; H% Q4 Z
241 }. J" `0 A" H. Z* [+ ]
25
% O. A6 o2 E/ A! W( OBat代碼! m: R8 F2 ]5 B; V$ m, W
build.bat1 E( ?3 _& P% B& i% l. D$ C
@echo off
& V) ^4 N& c# N8 t( adel  %1.exe
1 U( M" o3 a9 C$ H2 Fg++.exe  %1.cpp  -o  %1.exe  -std=c++17  -O2  -Wall -Wl,--stack=268435456 -D"__ISsupimoENVIR_", B8 A! }2 V9 d) D3 n7 b% n
- t" W) g7 I  T; d1 U1 n
@DELI;' S' n# E: e* B' w6 u/ ]" T% Q
' u7 w7 p4 Y0 p/ ]. O- L
run.bat
# h5 O! {8 ^2 E) c0 F) l@echo off
" {1 ^3 q; S& m& _+ K; w% v5 }%1.exe  <  input.txt( Z0 H/ F7 T1 w' E) L' C

& x: l4 }- ^6 i3 i3 u@DELI;
/ s; r! q6 f8 h$ H! ~4 @0 p) K2 {, V/ r! o' u% n
build_and_run.bat7 i: [8 k6 I, e* H1 |
@echo off
  G4 d. @6 g- u+ o0 Hcall  build.bat  %1
; |( F  c, w' j/ y4 b' `& Lcall  run.bat  %1  %2
3 U4 y3 Z' q7 @; }. X1
/ ^: ]7 |4 l+ q$ a7 `9 g2; J' C/ l; n/ W8 K
38 T+ {2 v/ \5 P; v- |# P3 X
4
. v7 c' e, L3 b, P5
0 t# v, c! x, y, q6
0 h4 b* A, x/ S/ l7/ C! v% Q" H; y) H, q
8  m  Y# z: \% k& ]
9  v3 a0 L7 ?) ~4 E
10
! V: m2 y2 ~# V% G5 n3 K" F/ [112 f6 y- @" }; }& K: \( P+ m7 U
12; k5 K: C' i' R' N* X
13
: S) P* D0 ~( M- s' {146 \  H7 `' u% R' C( N( o$ e! I- ~
15
7 c2 a  F! u" q$ j16# a$ r- p3 u1 N+ f0 V
17  X0 M/ u9 P; U
源文件) e6 c5 G; o* D1 z" u
#include <bits/stdc++.h>2 p- ]9 \0 U6 n3 k' O: C/ B
using namespace ::std;
6 V5 y" ]0 B0 n- Z8 B- y: Q# {  |, w5 U) e8 J, H, Z( A% a1 D. p; ?; p  C
//{ ___SUPIMO  ^. q: d# ]% U5 Z5 O1 z+ p3 {" ~- t
namespace ___SUPIMO{
( @# z9 I# v0 Q. ^! c+ s//{ Macro
# A8 T5 C, T: g" G  C#define  ASSERT_CUSTOM_( _op, ...)   if( !bool(_op)){ std::cout<<"Assertion_Failed(Custom):["<< #_op<< "],    Hint:["<< ___SUPIMO::Debug_::__ToString_items( __VA_ARGS__)<< "]("<< #__VA_ARGS__<< ")\n"; EXIT_;}
4 w! q# a9 {4 i* f2 f/ I1 l: q: S#define  ASSERT_SYSTEM_( _op, ...)   if( !bool(_op)){ std::cout<<"Assertion_Failed(System):["<< #_op<< "],    Hint:["<< ___SUPIMO::Debug_::__ToString_items( __VA_ARGS__)<< "]("<< #__VA_ARGS__<< ")\n"; EXIT_;}' M4 K% X- |% B6 w5 w$ {5 i* ]; {
#define  ASSERT_MSG_( _msg)
0 b5 @4 [5 I5 a6 V1 p% F#define  TODO_RunTime_( _msg)  ASSERT_SYSTEM_( 0, "@TODO: " _msg)
; h# g8 X0 ?7 J; }# x#define  EXIT_  std::cout<< "EXIT: Line("<< __LINE__<< ")";  std::exit(1);
- }( X9 t: |* f' h#define  EXIT_COUNTER_( _max)  { static int cont = 0; ++ cont; if( cont == _max){ string str = "EXIT_COUNTER(" + to_string(_max) + ")"; DE_(_str); EXIT_;}}! O4 m3 i& f+ o% \. a% F3 s# O
#define  FOR_( _i, _l, _r)  for( int _i=int(_l); _i<=int(_r); ++_i): M" n# W' ^$ K( a! b
#define  FOR_R_( _i, _l, _r)  for( int _i=int(_l); _i>=int(_r); --_i)
7 }" G) n. J4 C+ O. Z- b3 ^#define  DE_( ...)  if( ___SUPIMO::Debug_::___IsInDebug){ std::cout<< ___SUPIMO::Debug_::__ToString_items( __VA_ARGS__)<< "    {Line: "<< __LINE__<< ", Msg: ["<< #__VA_ARGS__<< "]}\n";}9 K) B' t6 {' ~& F6 ^% |
#define  NOTE_( _str)
+ n; M8 @4 K& h# d2 V$ P9 [7 o2 q$ [& p//} Macro
, R  ?' v; F9 V1 M5 e
& k9 {' N: Z/ H4 _0 ?. a" N' }. D# Wnamespace Debug_{/ `# l/ k5 i7 }& _/ O
    static constexpr bool ___IsInDebug = 1;
# U1 h9 T  ]1 i7 P- k    template< class _T> string __ToString( const _T &);   string __ToString( unsigned __int128);   string __ToString( __int128);    string __ToString( bool);    string __ToString( char);   string __ToString( const char *);   string __ToString( const string &);  template< class _T1, class _T2> string __ToString( const pair< _T1, _T2> &);  template< class _T, int _N> string __ToString( const _T (&)[ _N]);  template< class _T> string __ToString( const vector< _T> &);  template< class _T> string __ToString( const set< _T> &);  template< class _T> string __ToString( const unordered_set< _T> &);  template< class _Key, class _Val> string __ToString( const map< _Key, _Val> &);  template< class _Key, class _Val> string __ToString( const unordered_map< _Key, _Val> &);    template< class _T> string __ToString( const multiset< _T> &);  template< class _T> string __ToString( const unordered_multiset< _T> &);    template< class _T1, class _T2> string __ToString( const tuple< _T1, _T2> &);  template< class _T1, class _T2, class _T3> string __ToString( const tuple< _T1, _T2, _T3> &);  template< class _T1, class _T2, class _T3, class _T4> string __ToString( const tuple< _T1, _T2, _T3, _T4> &);  template< class _T1, class _T2, class _T3, class _T4, class _T5> string __ToString( const tuple< _T1, _T2, _T3, _T4, _T5> &);" l/ f1 E3 R+ v* O% i
    string __ToString_items(){ return "";}  template< class _H, class... _T> string __ToString_items( const _H & _h, const _T & ... _t){ string ANS; ANS+=__ToString( _h); if( sizeof...( _t) > 0){ ANS+=", ";} ANS+=__ToString_items( _t...); return ANS;}
4 n% N2 N7 h0 I! i% q9 G} // namespace Debug
" ^2 Z1 ^; H; f9 I
' P$ o) w$ ]; g2 ?& ]5 b# ^. L: u3 Q//{ Type
9 Q" F4 |( |2 gtemplate< class _T_> using Heap_small_ = std::priority_queue< _T_, std::vector<_T_>, std::greater<_T_> >;
4 ^- M/ b7 N  C" ~$ ^8 r7 o
1 D! S- f: `) v7 _, {, f  _struct Double{0 K& H5 S# R3 H
    using __Type = long double;  __Type Value;  static constexpr __Type __epsilon = 1e-12;
) S( d6 I7 ^9 }4 _9 h& h    constexpr Double():Value(){}  template< class _T_> constexpr Double( const _T_ & _a):Value(_a){}  friend std::istream& operator>>( std::istream & _cin, Double & _a){ return _cin>> _a.Value;}  friend std::ostream& operator<<( std::ostream & _cout, const Double & _a){ return _cout<< _a.Value;}
5 {" l, f( ?5 b+ t9 F5 b! }- o    bool operator==( const Double & _b)const{ return (Value<_b.Value? _b.Value-Value : Value-_b.Value)<=__epsilon;}  bool operator!=( const Double & _b)const{ return (0==(*this==_b));}  bool operator<( const Double & _a)const{ if(*this==_a){return 0;} return Value<_a.Value;}  bool operator<=( const Double & _a)const{ if(*this==_a){return 1;} return Value<_a.Value;}  bool operator>( const Double & _a)const{ return !(*this<=_a);}  bool operator>=( const Double & _a)const{ return !(*this<_a);}. @; J' ?0 K# M5 H
    Double operator-()const{ return -Value;}  Double operator+( const Double & _b)const{ Double ANS = *this; ANS += _b; return ANS;}  Double operator-( const Double & _b)const{ Double ANS = *this; ANS -= _b; return ANS;}   Double operator*( const Double & _b)const{ Double ANS = *this; ANS *= _b; return ANS;}   Double operator/( const Double & _b)const{ Double ANS = *this; ANS /= _b; return ANS;}  void operator-=( const Double & _a){ Value-=_a.Value;}  void operator+=( const Double & _a){ Value+=_a.Value;}  void operator*=( const Double & _a){ Value*=_a.Value;}  void operator/=( const Double & _a){ Value/=_a.Value;}& z- T; F4 J% n' y) Y/ E
}; // class Double
3 f3 m5 {6 ^" ?  z7 ^# @6 ^, G& G6 }+ S  N7 l
template< class _ModType_, __int128 _Mod> struct Modular{; g2 f" Y" x. \6 C
    ASSERT_MSG_( "_ModType_必须是{int/int64_t/__int128}");
. X- D2 [. P3 G    using __UnsignedModType_ = std::conditional_t< std::is_same_v<_ModType_,__int128>, unsigned __int128, std::make_unsigned_t<_ModType_> >;' x1 z8 @1 P0 V" _+ S  U# z! N  l$ F
    inline static conditional_t< _ModType_(_Mod)<=0, __UnsignedModType_, std::add_const_t< __UnsignedModType_> > __Modular = _Mod;  __UnsignedModType_ Value;
5 `6 b$ Z% \8 R2 `    Modular():Value(0){}  template<class _T> Modular( _T _v){ _v %= (_T)__Modular; if( _v<0){ _v+=__Modular;} Value = _v;}5 W% b' W" a4 X" l& T. e
    inline static void Set_mod( _ModType_ _mod){ static_assert( ! std::is_const_v<decltype(__Modular)>); ASSERT_SYSTEM_(_mod > 0);  __Modular = _mod;}
# e) G1 [& G4 I7 A    Modular operator-() const{ return Modular(0) - *this;}  void operator++(){ ++Value; if(Value==__Modular){Value=0;}}  void operator++(int){ ++Value; if(Value==__Modular){Value=0;}}  void operator--(){ if(Value==0){Value=__Modular-1;} else{--Value;}}  void operator--(int){ if(Value==0){Value=__Modular-1;} else{--Value;}}   Modular operator+( const Modular & _b) const{ Modular ANS = *this; ANS += _b; return ANS;}  Modular operator-( const Modular & _b) const{ Modular ANS = *this; ANS -= _b; return ANS;}   Modular operator*( const Modular & _b) const{ Modular ANS = *this; ANS *= _b; return ANS;}   Modular operator/( const Modular & _b) const{ Modular ANS = *this; ANS /= _b; return ANS;}  bool operator==( const Modular & _b) const{ return Value == _b.Value;}  bool operator!=( const Modular & _b) const{ return (0==(*this == _b));}  bool operator<( const Modular & _a) const{ return Value < _a.Value;}  bool operator<=( const Modular & _a) const{ return Value <= _a.Value;}  friend ostream& operator<<( ostream & _cout, const Modular & _a){ return _cout<< "Modular("<< Debug_::__ToString(_a.Value)<< ")"; return _cout;}  void operator-=( const Modular & _a){ if( Value < _a.Value){ Value = (__Modular - (_a.Value - Value));}else{ Value -= _a.Value;}}   void operator+=( const Modular & _a){ Value += _a.Value; if( Value >= __Modular) Value -= __Modular;}  void operator*=( const Modular & _a){ if( std::is_same_v<_ModType_,int> || std::is_same_v<_ModType_,int64_t>){ using __MultiplyType_ = std::conditional_t< is_same_v<int, _ModType_>, uint64_t, unsigned __int128>; Value = __MultiplyType_(Value) * _a.Value % __Modular;} else{ Modular ANS = 0; Modular a = *this; auto b = _a.Value; while( b != 0){ if( b & 1) ANS += a; a += a; b >>= 1;} *this = ANS;}}  void operator/=( const Modular & _a){ ASSERT_MSG_( "`Mod`為質數"); ASSERT_SYSTEM_( _a.Value != 0); *this *= _a.Power( __Modular - 2);}  template< class _T> Modular Power( _T _p) const{ Modular t = *this; Modular ANS(1); while(_p!=0){ if(_p&1) ANS*=t; _p>>=1; t*=t;} return ANS;}8 }5 |& x* v$ Q9 ~5 ~) T1 D& p
}; // class Modular
1 T, L2 Z. {! k- e//} Type( m$ x8 c! ?. I2 q- [# {

8 n6 @. ^; Z* a$ ]* _" @namespace Integer_{& i3 q0 J: h' \4 Q
    template< class _T_> _T_ Get_divideFloor( _T_ _a, _T_ _b){ ASSERT_SYSTEM_( _b != 0); _T_ ANS = _a / _b; if( _a%_b!=0 && ANS<=0){ if( ANS == 0){ if( (_a<0&&_b>0) || (_a>0&&_b<0)){ -- ANS;}} else{ -- ANS;}} return ANS;}
0 a- ]# X! I. m! V6 l/ e& G    template< class _T_> _T_ Get_divideCeil( _T_ _a, _T_ _b){ ASSERT_SYSTEM_( _b != 0); _T_ ANS = _a / _b; if( _a%_b!=0 && ANS>=0){ if( ANS == 0){ if( (_a>0&&_b>0) || (_a<0&&_b<0)){ ++ ANS;}} else{ ++ ANS;}} return ANS;}) k: l3 {8 n. m0 F$ f0 ]) M
    template< class _Type_> _Type_ GetPowerRoot( _Type_ _a, int _p){ NOTE_("a^(1/p)的下取整");  static_assert( std::is_integral_v<_Type_>);  ASSERT_SYSTEM_(_a>=1 && _p>=1);  _Type_ ANS = std::pow<Double::__Type>( _a, (Double(1)/_p).Value);  while( 1){ auto t = ANS;  for( int i=1; i<_p; ++i){ t *= ANS;}  if(t>_a){ -- ANS;} else{ break;}}  while( 1){ auto t = ANS+1;  for( int i=1; i<_p; ++i){ t *= (ANS+1);}  if(t>_a){ break; } else{ ++ANS;}}  return ANS;}
/ Y- G* O: }, p& e2 R1 W    template< class _TypeRadix_, class _TypeNum_> struct Radix{ // `TypeRadix: 每个进制的类型;  TypeNum: 所能表示的最大十进制数的类型`;
3 _$ I" m3 O# V5 s' H( x* x& S        std::vector<_TypeRadix_> __Radix; // 比如`Radix=[2,4,3]`, 那么所有的数为`([0-2), [0-4), [0-3))` 即表示的十进制数范围为`[0, 2*4*3)`; (Radix累乘值的大小 就决定了`TypeNum`);
0 i) p6 W+ n2 b+ K0 |        std::vector<_TypeNum_> __SuffixProduct; // `SuffixProduct[i] = Radix[i]*Radix[i+1]*...`;1 u) m3 T1 l& M- g% y
        void Initialize( std::vector<_TypeRadix_> const& _radix){ __Radix = _radix; __SuffixProduct.resize(_radix.size()); __SuffixProduct.emplace_back(1);  for( int i=int(_radix.size())-1; i>=0; --i){ __SuffixProduct[i]=__SuffixProduct[i+1]*_radix[i]; ASSERT_SYSTEM_(__SuffixProduct[i]/__Radix[i]==__SuffixProduct[i+1]);}}! l% s$ O# s/ X$ g/ a; `6 ?
        _TypeNum_ VectorToInteger( vector<_TypeRadix_> const& _v){ NOTE_("`v.front()`是*高位*"); ASSERT_SYSTEM_( _v.size()==__Radix.size()); _TypeNum_ ANS = 0;  for( int i=0; i<int(_v.size());++i){ ASSERT_SYSTEM_( _v[i]>=0 && _v[i]<__Radix[i]); ANS*=__Radix[i]; ANS+=_v[i];} return ANS;}% i7 e% e) {& Z, c& m4 J" w
        std::vector<_TypeRadix_> IntegerToVector( _TypeNum_ _a){ NOTE_("`返回值.front()`是*高位*;"); ASSERT_SYSTEM_( _a>=0 && _a<__SuffixProduct.front());  std::vector<int> ANS;  for( auto it=__Radix.rbegin(); it!=__Radix.rend(); ++it){ ANS.emplace_back(_a % (*it)); _a/=(*it);}  std::reverse(ANS.begin(), ANS.end());  return ANS;}3 b$ M9 T7 H* |+ C
        int GetBit( _TypeNum_ _num, int _ind){ NOTE_("`ind==0`是最高位");  ASSERT_SYSTEM_( _ind>=0 && _ind<int(__Radix.size())); return _num / __SuffixProduct[_ind+1] % __Radix[_ind];}9 K7 K2 o' j5 u# O9 U& F
        void SetBit( _TypeNum_ & _num, int _ind, int _v){ NOTE_("`ind==0`是最高位"); ASSERT_SYSTEM_( _ind>=0 && _ind<int(__Radix.size()) && _v>=0 && _v<__Radix[_ind]);  _num += (_v - GetBit(_num,_ind)) * __SuffixProduct[_ind+1];}
" [9 ?' U  L& ~( h- S$ {; W! q    };# J& x! ?1 x% q) F% o: ?
    namespace Binary_{
2 b- u3 @! T8 t, o& S        template< class _T_> std::vector<int> GetBits( _T_ const& _a, int _len){ NOTE_("a的低len位, @IF(len=-1){a的全部位}"); if( _len == -1){ _len = 8*sizeof(_T_);} std::vector<int> ANS(_len); for( int i = 0; i < _len; ++i){ ANS[_len-i-1] = (_a>>i)&1;} return ANS;}8 K1 S( v; u( Z3 M1 B
        template< class _T_> _T_ Get_sufixOnes( int _len){ NOTE_("返回值形如[0...01...1] 末尾有`len`"); ASSERT_SYSTEM_( _len>=0 && _len<=8*(int)sizeof(_T_)); if( _len == 0){ return _T_(0);} using Tu_ = std::make_unsigned_t<_T_>; return (((Tu_(1)<<(_len-1))-1)<<1)|1;}
: k5 d& N5 Y8 b! J  W: g        template< class _T> void SetBit( _T & _num, int _ind, bool _v){ if( _v){ _num |= ((_T)1 << _ind);} else{ _num &= (~( (_T)1 << _ind));}}) }- h( Z3 ?9 @- `0 l" u  G0 i* j  L) ]
        template< class _T_> void RemoveBit( _T_ & _a, int _ind, bool _v){ NOTE_("删除[ind]位 高位下移 且最高位补`v`");  ASSERT_SYSTEM_( _ind>=0 && _ind<8*(int)sizeof(_T_));  using Tu_ = std::make_unsigned_t<_T_>;  _a = (_a&Get_sufixOnes<Tu_>(_ind)) | ((_a&(~Get_sufixOnes<Tu_>(_ind+1)))>>1);  SetBit( _a, 8*sizeof(_T_)-1, _v);}
3 G" ?: x6 y1 n        template< class _T_> int Get_lowBit( _T_);  template<> int Get_lowBit<int>( int _a){ if( _a==0){ return -1;} return __builtin_ctz(_a);}    template<> int Get_lowBit<int64_t>( int64_t _a){ if( _a==0){ return -1;} return __builtin_ctzll(_a);}) O' X8 y$ ^2 D" n7 G/ x
        template< class _T_> int Get_higBit( _T_);  template<> int Get_higBit<int>( int _a){ if( _a==0){ return -1;} return 31-__builtin_clz(_a);}    template<> int Get_higBit<int64_t>( int64_t _a){ if( _a==0){ return -1;} return 63-__builtin_clzll(_a);}' w6 y$ U1 Y7 l
        template< class _T_> int Get_bitCount( _T_);  template<> int Get_bitCount<int>( int _a){ return __builtin_popcount(_a);}    template<> int Get_bitCount<int64_t>( int64_t _a){ return __builtin_popcountll(_a);}
( t; z; [- k4 s3 \: }/ X! B( `        // #枚举二进制子集#: `for( auto subST = st; ; subST=(subST-1)&st){ @MARK(0); if(subST==0){ break;}}`遍歷`st`中所有`1`的選/不選的方案; (比如`st=1101`, 則在`@MARK(0)`处你会得到`subST=[1101,1100,1001,1000,0101,0100,0001]` 一定*严格递减*);/ C( j3 P& R$ Z: d/ I( f
    } // namespace Binary5 V$ _/ s, _0 R& y/ f
} // namespace Integer
' f7 I9 o$ a" k4 F4 {' \) ^# B$ [3 [! C
namespace String_{
- w' {5 I& B3 W    void Replace( string & _cur, int _l, int _r, string const& _new){ ASSERT_SYSTEM_( _l>=0 && _l<=_r && _r<(int)_cur.size()); _cur.replace( _l, _r-_l+1, _new);}' N: P' h1 `9 m# {2 O. Y& U4 U
    void Replace( string & _cur, const string & _raw, const string & _new){ int m = _raw.size();  for( int i = 0; i < (int)_cur.size();){  if( i+m<=(int)_cur.size() && _cur.substr(i,m)==_raw){  _cur.replace( i, m, _new);  i += _new.size();  continue;}  ++ i;}}0 Q2 t2 o6 T% f" }7 _
    vector<string> Split( const string & _s, const string & _split){ vector<string> ANS;  string cur;  int n = _s.size(), m = _split.size();  for( int i = 0; i < n;){  if( i+m<=n && _s.substr(i,m)==_split){  if( cur.empty()==false){ ANS.push_back(cur);}  cur.clear();  i += m;  continue;}  cur += _s[i];  ++ i;}  if( cur.empty()==false){ ANS.push_back(cur);}  return ANS;}- }0 D: z" x7 k7 Q
} // namespace String
, O! z- `, q& h, X) {
0 X' f7 b% |5 C% m+ Y( anamespace Random_{
6 P6 l# z; D9 h8 B  A0 a    std::mt19937 MT32( std::chrono::steady_clock::now().time_since_epoch().count());    std::mt19937_64 MT64( std::chrono::steady_clock::now().time_since_epoch().count());
3 J) z* p! T! `: r  z& B    int GetInt32( int _l, int _r){ return (int64_t)(MT32() % ((uint32_t)_r - _l + 1)) + _l;}  int64_t GetInt64( int64_t _l, int64_t _r){ return (MT64() % ((uint64_t)_r - _l + 1)) + _l;}  Double GetDouble32( Double _l, Double _r){ return _l + (_r - _l) * ((Double)MT32() / (Double)UINT32_MAX);}  Double GetDouble64( Double _l, Double _r){ return _l + (_r - _l) * ((Double)MT64() / (Double)UINT64_MAX);}: _* s2 {4 K, Q/ r1 a! P: `; Z
} // namespace Random+ u' V% }, B) d5 J! t( F
) [" g# o8 ~8 U
namespace Object_{
' X+ x$ G0 U/ a! V, C4 I    const Double Pi = std::acos((long double)-1);' H- q6 n" L9 R0 y+ a& j+ J
    template< class _T_> struct __Int_0x80;  template<> struct __Int_0x80<int8_t>{ static constexpr int8_t Data = 0x80;};  template<> struct __Int_0x80<int16_t>{ static constexpr int16_t Data = 0x8080;};  template<> struct __Int_0x80<int32_t>{ static constexpr int32_t Data = 0x80808080;};  template<> struct __Int_0x80<int64_t>{ static constexpr int64_t Data = 0x8080808080808080;};
* l2 A! ?4 T7 T( f    template< class _T_> constexpr std::decay_t<_T_> Int_0x80 = __Int_0x80<std::decay_t<_T_> >::Data;; D: E* F% K9 m2 A. t0 n+ t7 C1 e
    template< class _T_> struct __Int_0x7F;  template<> struct __Int_0x7F<int8_t>{ static constexpr int8_t Data = 0x7F;};  template<> struct __Int_0x7F<int16_t>{ static constexpr int16_t Data = 0x7F7F;};  template<> struct __Int_0x7F<int32_t>{ static constexpr int32_t Data = 0x7F7F7F7F;};  template<> struct __Int_0x7F<int64_t>{ static constexpr int64_t Data = 0x7F7F7F7F7F7F7F7F;};! r6 M  w7 s' |. J( P  V
    template< class _T_> constexpr std::decay_t<_T_> Int_0x7F = __Int_0x7F<std::decay_t<_T_> >::Data;; [( _3 C6 F+ z) [
} // namespace Object
$ G1 z4 t6 _5 m; D6 T1 X" J6 Q4 x+ B' u3 r' V( Z! w" u4 `
namespace Function_{
: ~# N0 C& {! v( m2 m* B) l    std::clock_t ClockSplit(){ static std::clock_t __ANSTime = -1; if(__ANSTime != -1){ auto pre = __ANSTime; __ANSTime=std::clock(); return std::clock()-pre;} __ANSTime = std::clock(); return 0;}* N* Z! P& o7 Y4 P& ?; N2 w( `
    template< class _T> _T Get_GCD( _T _a, _T _b){ ASSERT_SYSTEM_( _a!=0 || _b!=0); while( _b != 0){ _a %= _b;  std::swap( _a, _b);} return std::abs(_a);}
+ D, w1 C( |1 e% x! p: _& y1 `    template< class _T> bool IsInInterval( _T _c, _T _l, _T _r){ return (_c>=_l && _c<=_r);}( s& F) |8 e/ n1 O; m4 g1 T
    template< class _T_> bool IsInSegment( const pair<_T_,_T_> & _c, const pair<_T_,_T_> & _p1, const pair<_T_,_T_> & _p2){ static_assert( std::is_integral_v<_T_>); bool ANS = 0; if( _p1.first==_p2.first){ if( _c.first==_p1.first && _c.second>=std::min(_p1.second,_p2.second) && _c.second<=std::max(_p1.second,_p2.second)){ ANS = 1;}} else if( _p1.second==_p2.second){ if( _c.second==_p1.second && _c.first>=std::min(_p1.first,_p2.first) && _c.first<=std::max(_p1.first,_p2.first)){ ANS = 1;}} else{ auto gcd = ___SUPIMO::Function_::Get_GCD( _p2.first-_p1.first, _p2.second-_p1.second); auto dx = (_p2.first-_p1.first)/gcd, dy = (_p2.second-_p1.second)/gcd; auto cx = (_p2.first-_p1.first)/dx, cy = (_p2.second-_p1.second)/dy; auto dx1 = _c.first - _p1.first, dy1 = _c.second - _p1.second; if( (dx1%dx==0) && (dx1/dx>=0) && (dx1/dx<=cx) && (dy1%dy==0) && (dx1/dx==dy1/dy) && (dy1/dy>=0) && (dy1/dy<=cy)){ ANS = 1;}} return ANS;}( O6 c' L& t8 J. Q4 l0 j3 j
} // namespace Function; e( i6 f/ p) a2 l, b$ X

/ |3 T6 u" Z4 I1 u" ?7 r7 K& E} // namespace ___SUPIMO
  r$ x5 ^0 U  [$ s0 K, h% N4 }$ ]; x- }" V0 u
namespace std {
# n, H( ]5 B( o3 H" f8 _    template<> struct numeric_limits<___SUPIMO::Double> : public numeric_limits<___SUPIMO::Double::__Type>{};4 C1 j8 u" L* T+ i/ ?! A4 A0 a3 X
    template<> struct __is_floating_point_helper<___SUPIMO::Double> : public true_type{};
& V9 _( p$ ~/ j( {    template<> struct make_unsigned<__int128>{ using type = unsigned __int128;};
7 P! z2 P$ ]4 q" F    ___SUPIMO::Double abs( ___SUPIMO::Double const& _d){ return (_d>=0 ? _d:-_d);}7 t3 L, h2 t( \% X; W# X
}& I2 O1 G1 m. l( C8 Q
//} ___SUPIMO
9 I. x% C9 `0 K$ O* O/ L- _5 B$ b5 Z0 [
using namespace ::___SUPIMO;
4 j$ A0 I$ y5 s
: C+ t3 T6 X3 nvoid ___Solve_oneTest(){, X3 X+ |' \+ e7 U( P0 t7 z
) I$ h9 t- |5 {) c
}
& t2 J# T2 C7 a4 J5 h: Y9 ]int main(){% `0 z4 o* z& q9 Q/ d* Q0 T2 E
    std::ios::sync_with_stdio(0);  std::cin.tie(0);  std::cout.setf( std::ios::fixed);  std::cout.precision( 9);
/ |4 I) r% |, Q* _7 i3 R8 e
! j, l% W: t$ G5 a$ I    auto ___Work = [](){ // 必须严格与*题目*的录入格式对应;& G$ W/ R1 x" ~
        constexpr int8_t mode = 0;
* w* l& Q2 |% c) \0 s        int testsCount;
1 e* B( p5 Z" F        if( mode == 0){ testsCount = 1;}  else if( mode == 1){ cin>> testsCount;}  else if( mode == 2){ testsCount = 1e9;}0 i2 l2 U  E* S
        for( int id = 0; id < testsCount; ++id){
" d- h) f9 k1 u) @1 N            if( id == 0){ // Global_Initialize
0 U* p4 `4 ?7 ^+ A) J2 a% c: t2 ?8 X- |8 s* W
            }
5 k" i( Q+ Y. Z9 F( U3 X            ___Solve_oneTest();& A! s- [6 O8 g0 J5 e
        }, F( n  w/ p! M' q/ s
    };1 ]2 C+ i8 ?- @$ v
    if( ___SUPIMO::Debug_::___IsInDebug){
8 ~  _7 @0 Z5 [3 y8 p        for( int id = 0; id < 100000008; ++id){3 M# ]: T9 G' }5 Q
            string flag;  cin>> flag;  if( flag == "___INPUT_-1"){ break;}  ASSERT_SYSTEM_( flag == (string("___INPUT_")+char('0'+id)), flag);
5 `3 A' C' v4 n$ `7 f            ___SUPIMO::Function_::ClockSplit();
5 }6 J2 Z* j; }' W, v/ c& {3 y            std::cout<< flag<< ":\n";* u% d% f' ~- A: d- q/ f1 t0 o7 \
            ___Work();4 h( c- j, F: K
            std::cout<< "\nTimeElapsed: "<< ___SUPIMO::Function_::ClockSplit()<< "\n\n";
' X7 u0 b* q; k; }* h( b' u        }6 Y" @% l' q% @1 |1 d) R
    }
# L, O  b) K. H. Y( u' q9 i5 U    else{ ___Work();}9 [$ F  A: [8 b2 U( N- i
# U. U1 h+ @9 y  Q% @& o* W
    return 0;6 g  X9 f) w& e7 L
} // main
) `; e. k. h: b' G" J$ M5 Z# K  Y: Z9 g; e
namespace ___SUPIMO {* Q3 W2 G3 a; b7 U( U! d2 h) j
    namespace Debug_ {
( Z7 O; b/ i* q7 M        template< class _T> string __ToString( _T const& _v){ ostringstream ANS; ANS.precision(cout.precision()); ANS.setf(cout.flags()); ANS<<_v; return ANS.str();}' [8 A: K# ?4 L. o& E8 z" M; _3 x
        string __ToString( unsigned __int128 _v){ string ANS; if(_v==0){ ANS="0";} else{ for(;_v!=0;_v/=10){ ANS+=('0'+_v%10);}  reverse(ANS.begin(), ANS.end());}  return "UInt128("+ANS+")";}
$ V  C1 \. c+ m' V4 s        string __ToString( __int128 _v){ string ANS; if(_v==0){ ANS="0";} else{ if(_v<0){ ANS+="-"; _v=-_v;}  for(;_v!=0;_v/=10){ ANS+=('0'+(_v%10));}  reverse(ANS.begin()+(ANS[0]=='-'?1:0), ANS.end());}  return "Int128("+ANS+")";}( I& u3 I$ O1 ?$ I# w7 Q( a
        string __ToString( bool _b){ return (_b?"true":"false");}. L5 O' J. I0 V+ T
        string __ToString( char _t){ string ANS="'?'"; ANS[1]=_t; return ANS;}
( Q9 a' x9 O; o4 d" {% s        string __ToString( char const* _s){ return string(_s);}
+ j* ]6 H& ~+ @2 K3 D        string __ToString( string const& _t){ string ANS="\""; ANS+=_t; ANS+='\"'; return ANS;}
, p  U  o2 r, A( U4 l# a+ U        template< class _T, int _N> string __ToString( const _T (& _v)[ _N]){ string ANS; ANS+="Array["; bool first=1; for(int ind=0; ind<_N; ++ind){ if( 0==first){ ANS+=",";} else{ first=0;} ANS+=__ToString(_v[ind]);} ANS+="]"; return ANS;}- V$ @+ X# V  Q  h/ }
        template< class _T1, class _T2> string __ToString( const pair< _T1, _T2> & _v){ string ANS; ANS+="Pair("; ANS+=__ToString( _v.first); ANS+=","; ANS+=__ToString( _v.second); ANS+=")"; return ANS;}
7 ?1 S2 l; Z" I  k6 v7 A        template< class _T> string __ToString( const vector< _T> & _v){ string ANS; ANS+="Vector["; bool first=1; for( const auto & i : _v){ if( 0==first) ANS+=","; if( first) first=0; ANS+=__ToString(i);} ANS+="]"; return ANS;}
' o- K9 l* Y1 X( L5 \% S2 N0 a        template< class _T> string __ToString( const set< _T> & _v){ string ANS; ANS+="Set["; bool first=1; for( const auto & i : _v){ if( 0==first) ANS+=","; if( first) first=0; ANS+=__ToString(i);} ANS+="]"; return ANS;}
1 n7 @8 ?; S2 q) w! q        template< class _T> string __ToString( const unordered_set< _T> & _v){ string ANS; ANS+="UnorderedSet{"; bool first=1; for( const auto & i : _v){ if( 0==first) ANS+=","; if( first) first=0; ANS+=__ToString(i);} ANS+="}"; return ANS;}
5 p0 d& L4 K* F6 F! @5 n7 j        template< class _Key, class _Val> string __ToString( const map< _Key, _Val> & _v){ string ANS; ANS+="Map["; bool first=1; for( const auto & i : _v){ if( 0==first) ANS+=","; if( first) first=0; ANS+="("; ANS+=__ToString( i.first); ANS+=":"; ANS+=__ToString(i.second); ANS+=")";} ANS+="]"; return ANS;}
1 x$ ^" k: V. ^* v/ O! L; k        template< class _Key, class _Val> string __ToString( const unordered_map< _Key, _Val> & _v){ string ANS; ANS+="UnorderedMap{"; bool first=1; for( const auto & i : _v){ if( 0==first) ANS+=","; if( first) first=0; ANS+="("; ANS+=__ToString( i.first); ANS+=":"; ANS+=__ToString(i.second); ANS+=")";} ANS+="}"; return ANS;}1 Z% [7 [" D& H- s( h& U8 X6 E
        template< class _T> string __ToString( const multiset< _T> & _v){ string ANS; ANS+="MultiSet["; bool first=1; for( const auto & i : _v){ if( 0==first) ANS+=","; if( first) first=0; ANS+=__ToString(i);} ANS+="]"; return ANS;}. y$ v4 A' A4 F2 o! w: f( l
        template< class _T> string __ToString( const unordered_multiset< _T> & _v){ string ANS; ANS+="UnorderedMultiSet{"; bool first=1; for( const auto & i : _v){ if( 0==first) ANS+=","; if( first) first=0; ANS+=__ToString(i);} ANS+="}"; return ANS;}
$ u  K& h2 F% g3 e        template< class _T1, class _T2> string __ToString( const tuple< _T1, _T2> & _v){ string ANS; ANS+="Tuple2("; ANS+=__ToString(std::get<0>(_v)); ANS+=","; ANS+=__ToString(std::get<1>(_v)); ANS+=")"; return ANS;}; W  i3 J! [8 L8 r; x$ r' K
        template< class _T1, class _T2, class _T3> string __ToString( const tuple< _T1, _T2, _T3> & _v){ string ANS; ANS+="Tuple3("; ANS+=__ToString(std::get<0>(_v)); ANS+=","; ANS+=__ToString( std::get<1>(_v)); ANS+=","; ANS+=__ToString(std::get<2>(_v)); ANS+=")"; return ANS;}3 ~& O& ?# r8 n" T8 i
        template< class _T1, class _T2, class _T3, class _T4> string __ToString( const tuple< _T1, _T2, _T3, _T4> & _v){ string ANS; ANS+="Tuple4("; ANS+=__ToString(std::get<0>(_v)); ANS+=","; ANS+=__ToString(std::get<1>(_v)); ANS+=","; ANS+=__ToString(std::get<2>(_v)); ANS+=","; ANS+=__ToString(std::get<3>(_v)); ANS+=")"; return ANS;}
% \  i5 R- L* a: W        template< class _T1, class _T2, class _T3, class _T4, class _T5> string __ToString( const tuple< _T1, _T2, _T3, _T4, _T5> & _v){ string ANS; ANS+="Tuple5("; ANS+=__ToString(std::get<0>(_v)); ANS+=","; ANS+=__ToString(std::get<1>(_v)); ANS+=","; ANS+=__ToString(std::get<2>(_v)); ANS+=","; ANS+=__ToString(std::get<3>(_v)); ANS+=","; ANS+=__ToString(std::get<4>(_v)); ANS+=")"; return ANS;}
6 `4 k+ K# W/ f2 l    }" H' p) S* [5 L9 W
}& U6 O  S0 U& ^- A) }% P5 T
1
) i( x1 T9 G  P2
, _8 C% I( E- C$ c/ r* m39 H7 V' g5 n1 x$ T
4; q) X! Y: B- }1 z9 @. R# R! r
5
$ G$ U7 L$ T9 T& m6: u( X3 l; Z7 @
7
3 S7 |2 z! G# b" S' l; v81 w0 T( \! ~) ^7 K# L2 x
9
2 U0 z4 f9 D# V1 D10# |! {7 I9 y! G3 {1 Q
11
- B8 p) Q# x1 D( U2 S- ^12
6 s/ k: `6 f% |9 R  \1 h8 j13! q' @1 k: Q3 `" `4 g
14
( `' |  J  G7 S% \6 K; m1 U15% S  m+ D/ U% l
168 A+ l& _) V7 p; B  n& c
17  i! U9 |! c) h# d0 x7 g6 V
18( Z" @) k/ t# M4 h- Q: i8 y% f& b
19+ o6 N( `6 [! m; W5 ?
20
) e0 I; z1 Z/ d5 F& q21. T1 G7 l( [5 G: s5 \8 W
22
* ^. @# x# k1 C23# \. r7 T! |5 j5 r
24
& N2 P4 b3 ~( M! x! F4 l) C252 U/ @5 Y8 E: i7 B
262 l1 q4 N) K- ^
27/ q4 R) @) D( {, P, T
287 J' K0 j6 w+ _* o. c
29
& d# N: _* ?* h5 k  C8 z& ]! Y  S/ d30/ y" _# W* e/ ^: F1 M* P
31( _1 s4 Z1 X9 A0 P' ^. [0 A) h9 l
32
3 \- A# w! @$ J$ N33- g' V9 J% p) C- [" T
34
+ [* e) T8 H1 J9 N$ j9 m5 A' W$ i354 h6 r- B' A, @2 u3 z$ H; \' S4 Z
36; x5 H: a5 G4 r3 m
379 ]+ X7 v9 S& R1 M6 f: b
38
0 \1 \! G+ K  H9 M, N- W39( e4 M" j+ F3 V7 s
40
: W' M! ~. w+ J# V8 g* `; N41# v. G( P% U; S7 q5 ^
426 M7 W8 B2 E' {7 u: ^8 N# y
43
7 P5 |' x! }+ D' M# i44
( D4 A. }( B3 c6 N. s/ U45# ~; P: m5 x/ C
46* [* ~, Q) m, ]" A6 a
47
5 U- C0 n& Q! t! j4 R4 Y- U48
9 m0 g, {8 J6 b2 y8 |5 m49
$ a6 Y: H2 ]0 ^0 P: w) L8 R: R. [0 Y509 l' a; B9 K( E4 d) ^: T( P
514 Y6 W% N4 [# t$ S
52
3 R9 b& {! Y: I2 e+ o  e53
/ I  Y0 C  A( v; z# {% i  B4 c54# n% Q# p& u& z
55
3 J% u2 F/ A0 X8 Q5 Z. p( c4 p6 ~& B56" a/ K0 L5 r! w
57
3 D# l# v; T) x; f; T# m# O# B583 \3 f8 s5 W# M: n3 `
59
2 Y% {) W% j, m) z% d1 o( L- ]+ r60
1 u) v4 g/ y' d% S: G2 L4 }61
& I9 b; e5 j( ^5 @+ [$ H9 u62
* T" m5 u( i6 C9 l$ E: W63# _$ p8 `' h% \( t! j& w1 e
64: I* r+ ~# `6 {4 S1 H3 y9 `; m+ d0 N
65
" m/ Q6 t1 Z" E) I; s* }8 p66* m6 P3 n/ ?/ u7 ^4 d; F, B# {
67
9 X( h. p) h+ @$ W$ V+ n2 z/ _683 e4 u1 y9 i! M+ G2 k
69: m9 x3 X6 s6 R4 z! R' g7 e! ]# b, d
708 _% x# F; \; k. f. d, y% {# K6 t
71# U9 E/ v8 A* z/ L7 Q) V1 p
728 q% l. U* M$ d5 @. ?
73. C+ U) i0 T1 M* R- F  k
74
8 D4 A- r& b2 ], P. g3 M75; v% x: _& ]# F& p
76! M' l& ~; v+ `
77
+ b+ L/ B' y" D, S+ n6 t78
, y7 Z% b$ X4 [- t5 i, ?9 z7 J79% g# g6 G- C4 e0 W4 k) {8 Q4 R
80
  w( P2 ]7 B! e( [0 z817 E3 o$ s# X, s! S, }
82! M0 m+ o9 F* X7 N* v2 O, `
830 J( R  O6 Z2 P1 c& F( a5 u: G9 `
848 {% K  d7 p4 q3 U" l9 w# C/ M
85
: `  C% R+ |2 w( @- V! o# e86
8 Y: |" y( O3 I+ g5 @" y& |, N6 B87
* T9 t$ A( |! p9 V$ F9 K' C  V+ D88
) C8 u* H$ E) L  `$ J/ U89
- P* t9 j4 t0 y' Q* V: H90* R8 K. t, `7 _1 q* a! y. n/ s
91
+ {) @% R+ z9 C, M" Q7 O2 A* `921 @1 e- k2 A2 r& L! o$ Z
93
$ T4 w( U" N7 U" k5 a- {" [' G94# B3 e0 C" l% p
95
+ D& k' W2 `8 |: u% e5 f96
, e8 j. N  d- a0 q8 j) t97& Y2 P  J) u0 c1 A" E- k
98
" f% o$ @$ ]6 C# T1 O. U) X997 e' t& r9 i; \3 K
100
. ^  H+ D; x4 m$ g8 w; F- v( E101
# K% u8 [' }, X" W2 o102
: c6 ~) N  @0 |. w) E, l1038 H: ?3 l, [/ x5 d! W) u* s
104
- _5 A. \5 v; O* g105
; ^3 y0 i2 x4 B106$ _. X+ j8 m2 \5 @5 }9 x- p; a
107
/ n$ \' E' b% H! L& c2 e108
7 M( w  H; `9 V3 _; g  K+ D109; Q  Y' n& X: ?2 J/ j& a: [
110( u. W0 s4 p! G" z/ N. x/ l
111# c2 y4 @0 A5 x/ b% P) _' ?8 m7 H
112
8 l* G; D3 n) b, I113
/ l) `: |+ N& T$ V+ V, ?- C  H$ F114
, D+ M* }, {0 O5 d115
+ \1 `" H* _7 U116
! D  ?' @) ]1 P' W. ?% x' t/ V$ O+ a117, a" d' F+ O) q9 {# u5 _0 f4 p" p& J
118" G/ {- m2 K+ V# J* ~, [
119
$ t* Z6 T( y# d; B2 W120
# V/ A( \7 f/ {  I4 L4 T121
( {, P1 Q# X: z# R4 \) a5 o% `122* k2 C, R) t' D* o
1232 M, H+ P5 Y9 v- u
124
2 N" h- V% Z. L7 k125$ l( B% a6 ^- p1 w1 V/ O
126% u' F3 t) K" n1 i
127
9 U7 y9 Q# I5 Q; U; Z' }% p128# Q/ H. Y) ^4 D* a
129
" J  [9 m+ S4 ~130- M; O% S; y: m. v0 I/ v
131) M/ U8 |# `$ P& J: |
132
0 e4 [) l" g. b% o, J133- W- p0 \/ n/ L* _; t5 |
134
8 Q) N! w: f1 e* ?135& n5 y; }' C  }, L& ?+ G3 [: J
1362 J# G, ]# Y! f% C/ Y
1377 Y8 a5 q: z$ M/ Q8 v& P# f* S' ~
138) s/ R2 P( F! s/ W7 A- Z7 y1 x
139
! o" v% l) r% {* l140( x' @: i$ _" `4 `
141
( v; l5 M6 D. m  j) o142
8 O1 x/ \' e5 \! h143% I! T) S& r( i
144
9 M; h$ l  C7 b! _  X145
0 U# M3 B! l- N6 ]1 y% L3 ]146
) @7 d" J) T7 u2 T! g$ ^3 r147
, ?0 w5 P+ x! \8 y+ c148
6 P( V& Q* K' {1499 Y$ V" L* d, D, C
1509 H$ s  D; j: Q/ }+ Y5 v  ?/ n
151
, E% M. F5 P6 M+ y* b8 t. O9 c152
$ T- f& V; z- ~% n  n  d2 M7 l7 Y7 L153; I5 Y6 m# Z) N) Z' o
154
; ?7 }, ~  n- u. k155
1 I& z# @! @6 J" k156
/ T5 ?: k! T9 I% F1 V) Y/ p157
( s/ F3 l9 d2 |2 d) |1589 Q8 j7 X. ~5 p$ h3 Q& ^5 G
159
2 p& Q. u  q+ C1 R, K! b/ F5 B' B160
) [4 n& G4 Z4 y$ ~161
$ u- ?- M, M: r5 d1625 F6 w6 o. P, X+ n. N! f, v
之所以把___Solve_oneTest()單獨寫成一個函數 而是放到main函數的for循環裡面, 因為: 當我們要進行特判 比如if( N==0){ cout<<"YES"; return;} 這裡的return 就是結束當前測試, 可是 如果你放到for循環裡面 你可能認為 那用continue不就可以了? 錯誤, 因為如果你內部還有for循環 這就出錯了 即此時continue不是對*外部的for循環*生效; 所以 必須要寫成函數形式;5 E9 V6 ^5 q: r; [
7 X+ _) u& S* p/ O8 u' M
Global_Initialize% \7 s4 i* P+ A- C" A& D- `! I8 R
专为力扣设计的, 即全局(多组测试数据所共用的)数据的初始化;/ R( h! c2 h& e$ a3 X5 P

! T) Q8 e3 n6 _& Y6 H( [$ Y; aString. Q# O+ U& X' H- T* _+ C& Y
Split的答案 一定不会有空字符串;
" N7 _4 B3 {! v# p$ F- R3 Z他是从前往后贪心进行的, 比如"xxx" 以xx分隔, 那就是[xx] x 即答案是最后的那个x; 比如"xxxx" 以xx分隔 那就是[xx] [xx] 即答案是空的;' V( ~$ f0 [) q+ z4 \: U5 {' K

; T% o# t0 K. o@DELI;7 s$ F. g. D1 ]" K
& A3 ^& Y! n* Y' z& E8 j4 G
Replace的本质 就是Split函数, 即比如你Split得到的是? X ? X ? (将X替换为Y) 则答案就是? Y ? Y ?;
3 h( M' t' n% b" f+ |6 X. 比如S="xxxx", raw="xx", new="x", 那么答案是xx, 即先是[x] xx 然后[x] [x]; (并不是[x] xx 然后[x] x 然后x);; B# i( D) D' P1 Y, ?
/ `6 I: I  H: t5 I) l2 x/ f
Debug, \  z" F, F  c1 K$ m  G
if( ?){ Debug::__IsOpenedDebug = 1;} 和 Debug::__IsOpenedDebug = (?); 这两个 是不同的!
7 d# F6 E) y, y+ V前者: 他是在特定情况下 打开调试, 但是他不会关闭调试; 而后者: 他要么会打开调试 要么就关闭;
/ d* P. ]1 e* e/ j  L3 |; {  f前者 通常用于 针对某个子流程而调试, 比如... [T] ... 最开始我们关闭调试, 然后到[T].入口时 打开调试, 然后到[T].出口时 关闭调试; 即整个过程 我们就调用了三次IsOpen = ?命令; 这通常在DFS时 使用的较多, 即符合某种条件时 进入某个DFS分支时 打开, 然后回溯回来时 关闭;
- x3 G3 a3 v+ _而后者这种方式(即不停的根据条件 打开/关闭调试), 一般在非DFS的场景(比如FOR循环)里 会使用, 比如只对所有奇数进行调试;
- ]+ k8 w5 C3 V即前者 他是针对一个连续的子段, 而后者是针对一个序列里 满足某条件的若干元素;
2 q& k1 m( s( ~  U" k( e" s3 A0 D# P3 q3 i0 Y" r* O8 m
@DELI;3 [( w( g, X! h3 R
  X6 \# t  D6 Q. C% ?) `9 t% }
有個疑問: 為什麼要把他轉換成string 而不是直接cout輸出呢?4 L* H0 f9 n3 B4 f' V: \; ?
. 可能是多了一层封装? (但毕竟你这个模块 就只复杂Debug输出啊 有必要再多封装一层吗?4 m- H/ J( d! S3 s/ Y3 t
1 ^6 I: E+ l. j# B' {/ x. O
@DELI;! r, j* M$ q$ Z1 C2 s. u% l

9 R9 w) V; f2 x9 ~- AINFO_里, 不可以对#__VA_ARGS__直接用,逗号分隔, 因为他可能是INFO_( F(a,b), 3), 所以你还得判断括号;
  L, o+ o. O& U- M& T2 J9 P7 @. O8 ?7 g" C3 h7 q4 N) x/ G
@DELI;3 }6 U( p" I8 N  J
& T6 k6 G; d/ a6 G& K- M7 |. T
T A[10];數組類型, 你可以直接輸出DE_(A);
8 F/ z! K" k  h3 t+ w! @5 {5 ^/ vDE_( (T(&)[5])A); 這是輸出A[0,1,2,3,4];% a) c& S' z, Z* V

. l; ~( Q7 u! @auto A = new T[2][3] (此時auto == T(*)[3]);
" ^# {2 J- e- e; S6 D. ^. 要輸出他的所有元素, 此時直接DE_(A)是錯誤的(他是個指針地址), 正確語法是DE_( (T(&)[2][3])*A), 注意 *A的類型是T(&)[3], 但你把他強轉給T(&)[2][3]是可以的;+ ^" X4 A) S5 `; |; e

7 M* S& r, C0 _3 i3 m& Y@DELI;/ F! n' {% I7 n
; L$ G, F% H+ g; x0 A" {$ B
__Debug_list的參數 必須是const _H & _h, const _T & ... _t引用 不能是值傳遞;
) @6 S3 u, x7 d6 I+ D比如對於對象很大的情況(圖 本身都已經1e6級別的大小), 那麼 這已經不僅僅是效率問題了, 因為參數用的是棧空間 這是會爆棧的;* `6 R3 ]; X/ \5 \$ e

* a1 N9 N  Q( ^@DELI;
2 G6 e( k9 [" U  I/ f) d+ E/ }9 G! M6 U) F% M, G
我们使用__Cout自己的重载函数 而不是去重载operator<<, 一个原因是 对于char/string基本类型的重载 此时和系统的就冲突了 (你需要再单独写个函数使用is_same去特判) 所以 不如就不使用系统重载符了 直接自己定义函数; 第二个原因是 其实把 两者本质都一样 我们自己写个__Cout函数 等于多了一层封装;
4 m, q' S  G5 q8 u% |7 X/ @( E& c) q/ \( t' R2 f) z1 |
你必须要声明/定义分开 這是為了實現對嵌套的輸出, 比如对于vector< map<int,int> >的输出 他使用了Cout( map<int,int>) 因此 你必须要有其声明在vector實現函數的前面;5 g% A: |* T) Y' e; ~4 T

# n8 y# c& _8 x6 y: D& t8 w1 H如果是自定义类型 他会进入到Cout( T) 然后调用cout<< T, 即你的自定义类型 需要有重载运算符;
1 J) e  y9 Q/ X
$ z7 v  Q8 i0 y# m& A) I( W@DELI;
5 L8 p# L1 w3 ]- @5 o& h/ A* m$ K/ {9 z! Z1 ^
__Cout你不需要寫成 像ostream& operator<<( ostream&, T)那樣, 直接寫成void __Cout( T)即可, 這是因為: operator<<之所以要那樣寫 他是要實現cout<<a<<b<<...這個操作; 而__Cout 不會調用__Cout(a) << b這種操作;5 W+ ^" h- e( P

2 s: }: K+ |. e' aASSERT報警宏
6 A+ \  j# m9 ~5 O! `#如何关闭某个子模块的ASSERT$
! i. d. A6 m9 k1 Q对于算法模板A, 他里面有很多ASSERT_SYSTEM, 为了优化效率 如何把他们给关闭掉呢?
0 c1 {" j/ a  t' x
2 i8 c9 u" p& D4 s+ d. X#undef  ASSERT_SYSTEM_) \, z3 a2 s# h( n4 D3 \6 T4 b
#define  ASSERT_SYSTEM_( _op, ...)
5 f* i' w4 W+ T3 b* Y! Y        namespace A{3 h+ j2 u$ m. s' I
        }9 u" O" P3 M' e- ]
#undef  ASSERT_SYSTEM_    ' q- r# J( \* ]) e9 _. `6 p
#define  ASSERT_SYSTEM_( _op, ...)   if( !bool(_op)){ std::cout<<"Assertion_Failed(System):["<< #_op<< "],    Hint:["<< ___SUPIMO::Debug_::__ToString_items( __VA_ARGS__)<< "]("<< #__VA_ARGS__<< ")\n"; EXIT_;}
7 c7 t: H7 g9 M7 h8 Y10 d% Y7 P4 N0 Y& D7 ]
2. i+ j& N) h  Q7 ?' K: a. p
3
: s8 H! Z! O5 `  J/ t% }4# ^: u  `2 L4 }5 C, w
5
7 i5 K8 a' U0 e0 m) `& }6
  M4 u! n4 J: X4 B; ^# S. 也不可以不写#undef, 但他会有警告warning: 'ASSERT_SYSTEM_' macro redefined;1 H) q' `/ V9 S  t
: u; u! {5 S% D9 U2 O! _0 e; L- ~& M( x
@DELI;
! U" e$ X# L9 E. E( \5 r+ C& T- l5 O9 X& g
ASSERT_CUSTOM_: 用戶自己的程序裏面 使用這個宏;; k% T. N+ W( Q( f8 k' h# Z. B5 V
ASSERT_SYSTEM_: 算法模板裏面的報警 都使用這個;
* T, `. w, H$ y" C% J9 }+ S/ N
7 Y& W+ `- j: L' x  ^' B: X, M) x& J& t9 n5 H
為什麼FOR_的宏定義是 (int)_r呢?8 I; S1 }+ p3 ]7 N$ q7 i- j
對於uint32 a = 0, (a-1)的值 是111...111, 於是for( int i=0; i < (uint32)-1; ++i) 這會死循環的;9 e8 ^9 u: u8 v7 _+ N; M
但是 把111....111 強轉為int, 她就是-1, 即int i = 0; i < (int)-1; ++i) 這是正確的;
8 M, W2 g$ i: S  m! ~: ^3 Q; I  f# Y. i6 @
@DELI;
6 q. E) I9 U( U5 n4 t
; ~7 G! `0 d6 R  c  D; q這3個報警宏 都有2個模式:6 V$ W/ H2 \. g1 [& `
1(默認模式):[如代碼所示];8 O7 G+ f/ p' I/ x/ S. A
2(優化模式):[你自己把他注釋掉, 這主要是為了(提高程序效率/便於找到程序BUG)];6 q: O* k9 M7 p& z0 _
. 比如默認版本是#define A x, 那麼你就把他改成#define A (void)0 // x, (注意後面的注釋// x是不生效的 預編譯時會被清除掉 即到時候是(void)0; 而不是(void)0 // x;)2 Y; @1 Z  G+ m$ t; l6 b0 c
* W5 X- y$ b: M- {  F
ASSERT_MSG的優化版本 即static_assert(false), 此时在开发阶段就會報錯 也就是你會發現所有的調用ASSERT_MSG的位置, 就可以发现有可能存在的错误;
- C# X- C# g5 Q4 b5 t+ J  {+ H0 z% D4 r5 U/ s. ~" s# _
@DELI;* f6 \/ j9 \+ j0 ~

, H) J" }+ Z2 J% Y$ B#ASSERT_MSG_( _msg)#* l4 J9 F0 c5 s  E6 d9 _0 o3 u
这是完全给用户提示的 程序无法测试其正確性 但你自己必须保证他是true; 比如取模除法 mod必须为质数, 就可以是ASSERT_MSG_( "mod必須是質數");
9 I( Y% J4 {6 u
+ e  K% ^: Q4 s@DELI;1 c& A" F6 A( K# A
4 [+ }  p3 ]2 U6 T1 P  |0 O" n
#ASSERT_WEAK_(op) (void)0#
7 j; S/ s8 p% N% [1 O即使op为假 也不会报警, 但你自己要保证他一定是true 这是为了效率;8 H1 |2 Q. ]) Q5 E6 @# c: n# ^! u

+ ^* J1 x2 b4 _4 jModular
! g& W* G, ^6 |' sModular的設計思想是這樣的, 她有2個模式: 對於using MOD = Modular< T, X>, T必須是有符號int/int64/128;4 V7 x7 r. A; Y- _) k4 r1 b
1: 你的Mod模數 是不變的const常量, 此時 這個X是常數, 即在編譯期 模數就固定了;8 R( d; \5 s! B2 p
2: 你的模數 是可以改變的, 此時這個X <= 0(你任意設置一個值即可), 此時到了運行期 你可以動態的通過MOD::Set_mod( m)去設置他的值 且這個m參數的值 即模數 她必須是在T的正數範圍;
3 g) }  M8 X( k) R* s不管哪個模式 假設你的T=int 你最終的模數 一定是在[0, 2147483647]的範圍內的 (而不是uint32的範圍), 而且你的值Value 一定是unsigned T類型, 為什麼要這樣設計? 因為 當你進行加法運算 此時 你不需要轉換為int64 她的加法結果 一定是在uint32範圍的;6 T) Z# Q- T( f3 o. a7 [3 e+ K) j. q& D

$ D+ a# ~8 A: b6 c  K0 r' n@DELI;3 e4 M. K) P  t, W+ d
) j6 B; h( m. M8 ?" r
對於乘法操作, 如果是int32/int64 則直接轉換為int64/int128來進行乘法, 否則對於int128 則執行二進制乘法(她會調用取模加法 是不會溢出的 這就是為什麼你的模數 必須是有符號範圍);
$ `: Q0 B1 P# ~' P& s' O: U- l8 h9 F* M% b% d4 m
@DELI;2 E/ R6 J, W+ }, q* d' r
% r. }8 v, n; P- j) \! p
template<class _T> Modular( _T _v)這個構造函數裡 你不能對他進行is_integeral的判斷, 因為對於__int128 他不滿足條件(可能未來編譯器會支持 但現在他的返回值是false);  z  @" h0 g- W* j8 Y7 S" h$ F4 h4 A7 H% _
- q$ _# k) Q9 q3 G! n3 W
@DELI;, {; q0 i- e9 m$ r8 R  H1 A( k

- g. m2 M6 @4 n0 M9 V* N9 a基本使用
  S( g4 l& }" t% ~7 E' S
% _" s" w1 b  _using M1 = Modular<int, (int)1e9 + 7>;5 d3 X+ D1 v# K% i" h
所有`M1`的對象 他的`Mod`都是*int常量*;! \! r& e' O: I' {7 F( B7 L
! m( n8 l8 o; F& w
using M2 = Modular<long long, (long long)1e15 + 7>;
/ R7 p- b4 D! r5 s所有`M2`的對象 他的`Mod`都是*long long常量*;
& W. \! l5 B4 a* o: P1 Z5 a, v: Z/ C' T
using M3 = Modular<int, -1>;
( T, O' b1 P: X, @" C9 ?M3::Mod = ?; // 由用戶錄入 (這行代碼必須在*運行時* 即放到函數域裡)* l4 Z2 `9 W( Q5 S9 E) C4 N
所有`M3`的對象 他的`Mod`都是int類型 且等於`?`;
; G, V" a$ M1 S1 C6 i! Y8 v" g
4 ~0 e/ p: _$ ?' H, y1 E8 s& Iusing M4 = Modular<long long, -2>;
3 C1 I( e( c- e. RM4::Mod = ?; // 由用戶錄入 (這行代碼必須在*運行時* 即放到函數域裡)/ ~. G5 ]2 |" L) s
所有`M4`的對象 他的`Mod`都是long long類型 且等於`?`;# N, Q1 n. A8 e1 ?2 C( J5 X# y
, p1 n! @  G# Z# l0 i
using M5 = Modular<int, -2>; // 注意此時要和`M3的<int,-1>`區分開來 即不能寫成`-1`, 否則`M3,M5`就共用同一個`Mod`了;$ |/ h4 f+ s) \* l9 S& O; V: U; Z

# o: Z$ ^- p1 v5 g3 C, M
3 \4 _1 h2 n/ q' o/ R$ B@DELI;
- C# m8 J" n4 Q0 Y
# {, K4 r; T' f% \. a% N' b  j6 wT_ Value; // 一定是[0, Mod)范围; 不要调用`obj.Value = xx`(他不是规格化的) 而是使用`obj = xx`;4 y# d. M6 ?, Y2 G
1
9 |0 w% z7 W0 ?0 S#除法#
6 P" f3 B# b5 x5 _5 t/ Q2 D) T调用a / b的前提是: (1: Mod是质数), (2: b != 0);
6 t) z  X1 i% D. s4 x
6 w/ j: @0 c5 b" K- D9 M% f@DELI;
# y+ X. t& ~- {
7 _! X$ T/ M2 g. X1 K1 u#BinaryMultiply#! t% h! J" i3 y
使用a*b(重载乘法)的前提是: Mod * Mod <= INT64_MAX; 如果是Mod+Mod <= INT64_MAX 就不能使用重载乘法了 可以使用当前的二进制乘法;
( x' N3 w. {2 V" e+ T9 Z/ U# O" \* k% n
@DELI;6 {; ~) Q; S$ t2 ?, E

, j% E0 Q- N* a' `  o#__Cout#: Y9 }  n) O: P; _7 I1 C
这个函数的目的是: 特判, 即对char/string/const char *的输出 重载, 之所以不是放到<<重载运算符函数里, 是因为 如果是<<重载 这些基本类型 就和系统cout的内置重载函数 冲突了;) }# k7 `- i# M) Y8 E; J
也就是, 比如对于vector的重载 是放到operator<<里的, 而对char的重载 是在__Cout里;
' F; R! j* R4 k8 U0 T* M, l- I5 H! Y  G7 G0 s
函數" n; _3 |* i( m4 L( b* x9 }
#IsInInterval_#
4 c% i: N$ h$ `1 i' b. IsInInterval_(c,l,r, true): 判斷是否滿足`c>=l && c<=r`, 即在這個區間裡;
, t: H$ M- u) A+ r. IsInInterval_(c,l,r, false): 判斷是否不滿足`c>=l && c<=r`, 即在這個區間外;
, y7 m  ]! U( w$ A6 F; C5 Y$ f* L; I13 |5 B* B$ A4 h/ R
2
/ ^" H" [8 R) x8 H5 t* @$ v) U: E3' t) N9 A/ P5 i( q- }
Integer8 N( V( w& a6 q2 P1 M/ Z0 I
GetPowerRoot( a, p), 比如令T = a^{1/p}, 则返回值为T的下取整;2 G3 z7 Z7 k1 j6 M" b; h# H
2 ~+ J. G3 f. Z$ o
@DELI;9 ^1 y1 |/ f! V2 |' [) E4 S
, D$ n: W1 Q$ g- I9 ?
VectorToInteger和IntegerToVector是互逆的;
) i3 E  Z! D* B4 ]  [數字的高位 就對應 Vector的開頭; 這樣設計是因為: 對於一個整數321 我們通常是從高位開始閱讀 因此高位對應vector.front();  s" m, V/ V+ S% R
. 比如, 整數321 (3是高位 1是低位) 她對應的Vector是[3,2,1] (3是開頭元素);$ Z# O# H* m! N2 k8 E

# L7 A8 x: q/ m& Q8 P@DELI;
% K5 r0 l- W# }+ F6 R: G3 s5 E* b
; n  ?, ^$ d8 a. W: S1 J) v使用该模块里的任何函数 都是谨慎, 最好就是在调试期间调用, 你要充分考虑好他的实际效率问题;/ e- d, v6 O0 e/ _7 ]7 U. i1 S
比如VectorToInteger( {a,b,c}, 5)这个函数, 其实 你可以自己手动写成a*5*5 + b*5 + c, 没必要去调用这个函数, 因为此时你已经得到了{a,b,c} 他的长度是明确的 去调用这个函数 反而效率非常低;
: o! f; f" A7 {: y6 Y6 `0 u2 D' {% A  D. t0 B) b5 E' r& l3 t
@DELI;
% b" m2 o1 V0 W/ u
# [" h- g5 P2 C: G3 Nvector<int> IntegerToVector( _T _a, int _len, const int _radix);1 N3 [! r6 b' j4 a; r
比如a=10, radix=2, 他對應的2進制表示為1010, 那麼此時你必須保證len>=4 (否則會報警);
/ ~) p# ]6 Y/ i! A% Z2 m. @IF(len==-1):[答案為[1,0,1,0]], @ELSE(len!=-1):[答案為[0...0,1,0,1,0](即前面補充前導零 答案長度為len)];
! a) D& m( K$ N8 B; F. F: {) y% `3 F& ?
@DELI;2 s7 z8 I+ I: {9 c# o' }

; P6 r2 Z0 R  V, ?% b( RSqrt( a, p)& q# {. C1 D  Y' S
要確保a>=1, p>=2, 假設答案是浮點數b 且返回值是b的下取整;+ q3 `: [; `0 M: k
這個函數的主要目的是 判斷a是否是p次冪 如果是則返回其p次根;, P! n" B2 K5 b; [3 D( Y- `/ p
. 由於b = pow( a*a*a, 1/3), 此時b可能是a-1/ a, 而答案是a, 所以要判斷 是否b+1 == a;# X$ s/ ?5 O, U( L" _; Z" G  Z
; v7 S$ A( i6 T5 Q, o
@TODO
7 W9 L9 T, O" A  V' z0 P1 cModular里面, 我们用unsigned T来存储结果, 但实际上 你的取模值 一定是[0, T)范围的, 即只使用了一半, 这是因为 当涉及到+-时 此时不会溢出;3 i8 x& n, M" P3 Y
. 但这有缺点, 当你Modular a = -2时, 此时构造函数是-2 % 5 他会变成int % uint -> uint%uint 即-2会变成uint 这就出错了!!! 因此要写成int%int;
* L$ {) {( ]8 o4 C最好是, 你就用T来存储结果, 当相加时 他虽然会溢出 但其实他还是正确的! a += b; if(a<0){ a -= Modular;}就可以了;9 `& c  {5 k# @; p6 b

9 m- H, X( y2 u5 j( q错误7 T" Z- n  G* w, A; j& }3 X+ J$ f
is_floating_point_v< Double> 他是等于0的! 因为Double是我们自己的自定义类型;& w0 Z% o) M- o
你可以写以下代码后, namespace std{ template<> struct __is_floating_point_helper<Double>:public true_type {};}, 此时 就可以了;
# p# q' I9 X  w) Z3 Z8 Q4 R" w/ N# D: C6 y
算法模板编写规范
+ {; G% y/ D9 r( S. l错误& N- `3 X) r9 E4 Z6 M# H
模板类 不要写构造函数, 因为我们可能写到全局域里 ST s(而不是ST s(??) 此时不能有参数;9 s* E( a( J4 V$ ]" R7 o; P& p

* ]. J7 L- v8 M$ m1 `  k# M$ B2 A@DELI;: W6 X7 m" T4 ]/ i

" [; S# T- y; c' n) X5 d/ b4 T不要写namespace ST{ using T = ?; vector<T> DP; void Work(){}}这种代码; 这样会导致ST是一次性的 即T是唯一的; 然而namespace不能加模板;
. o# [4 X  q! |/ c一种做法是: template<T> struct ST{ static vector<T> DP; static void Work(){} };, 但这样有2个缺点: (DP需要在类外定义 因为他是static), (由于ST是类 而实际上 他里面都是static的 不会用到他的对象 这就违背了类的初衷了);
" v  O/ v0 }  l6 O7 A最优做法是: namespace ST{ template<T> vector<T> DP; template<T> void Work(){ 使用DP<T>;};- w' q5 S: _+ g, H4 [8 }, {
+ m3 R+ _6 n4 X/ y6 z- `
性质
1 _4 {( B( X8 z4 ?7 D模板类里放大数组constexpr int N = ?; int Arr[ N]; 等你用到时 再把?赋值, 这种方式 他确实是效率比vector<int> Arr要高, 但有个缺点是 你到时候的类对象 就不能放栈空间了 需要是static ST s 否则大数组就爆空间了;
- ?; N+ I, @4 u" Y" M
( O6 c( P" i7 @0 X# C@DELI;* f3 Z$ m2 d6 P. ]9 i

! e- H; V1 X. h不需要寫一個TODO_STATIC_的宏, 對於靜態的@TODO, 你直接寫成注釋即可: @TODO: xxx, 然後實際使用時 再把他給注釋掉即可;/ [; Z. M% `) j  O# K. V
4 `& H& m; @/ f& d4 n: C
@DELI;
( M: |2 d6 C8 D( I- Y( ]- E& x, u' R4 @
#讓某個函數 必須在程序開始後執行一次 且只能執行一次#/ P" ^* E3 f- t1 t

5 N) g4 Q+ @9 J, D# I% ?% R  Dvoid Init(){
9 t- l! P& C/ l  N        EXIT_COUNTER_(2);
6 i, D" L5 x# _" F* o& R}  Q) A0 i+ d& s
@TODO: Init();1 @  e5 m) v6 F3 w7 ~
1; m3 B6 W  k/ b  Y8 c3 _! Y4 F5 _, F
2
4 K9 g! X& x: r9 Z* U. q3
6 m- K: W& R: I4
& J' R! s6 j& r4 f4 s這類函數 通常是不可以有函數參數的 (比如篩質數函數), 也就是 她的參數 是根據題目的最大數據範圍 而不是錄入的值;
( z  q: T5 l$ `( a- j: Z0 p0 B* {) z" t8 h
不要用__attribute__((constructor)), 她是報錯的, 因為他不是在運行時執行的, 而我們的需求是在運行時執行;
9 w. F$ Y( L/ H# U/ \( n
) I: k. h/ [$ {2 M1 D, E@DELI;  N6 Q5 O0 [! r
  J3 P1 b+ e1 k7 h9 ]" Z% j
#類/命名空間的Debug調試#
( S+ P* E# G: M5 U& ~4 k- e! Q* u" M! X2 k' a# j/ e! a
class ___X{
4 W( |5 R4 h5 P1 r        friend ostream& operator<<( ostream & _cout, const ___X & _a){
7 f5 T" d( V7 y4 g5 j) ]                _cout<<"\n"; 8 v7 u9 E& D! |+ y( r
        DE_( "___X-Debug-Begin");$ ]. M0 g' {: q6 I: I
# Z1 T, y' P% d+ V
        cout<< ?; // 此時不可以使用`DE_(?) 或 `Debug::__CoutItems(?)`, 必須使用原生的`cout`;
& Z7 A: ?$ D$ L
/ Z3 ~. z' X1 B: l% R        DE_( "___X-Debug-End");- a' P1 t4 d# k
        }' [+ t; g0 ]1 ^. z! B/ `* g3 B
}
& d; R, ?* o2 N: }% i# d; ^8 f  C& A
namespace ___X{
+ e$ X% S% v2 H+ V8 S/ z        void Debug(){
6 N/ G3 o, e  Z$ L                DE_( "___X-Debug-Begin");
" H' X% Y) L* P. X( _* q+ H8 J
, Q5 H) e. v( X/ h        cout<< ?; // 此時不可以使用`DE_(?) 或 `Debug::__CoutItems(?)`, 必須使用原生的`cout`;; U; l0 ~  V, L0 w8 \1 Z
0 @6 r7 J! B! a+ i* C; k
        DE_( "___X-Debug-End");" F- G2 u; ?: k2 f
        }
$ X- h, T& C# j7 e& I}
9 ^- _9 s+ }9 r7 C4 U( N
& a8 [8 E( N; c1 T@DELI;7 S: k8 v# V% A% t
" \) B/ h0 X9 m) U5 U+ ?2 ~" Y
#嵌入模板的全局变量#3 M3 k8 a# ]: y; H# F7 ~8 n

: X9 D- M' s8 M( L- Q{ // ___XX' _2 t" H8 k% Q# [  `+ c, G
        const int ___Number = ?; // 这里就叫做全局变量; 要以三个`___`开头) U1 l4 h# a7 _- }0 F+ V& j% d
        int ___N = ?;: V- E2 H" [+ D
        for( int i = 1; i <= 5; ++i){  X4 X6 r8 p& g0 p- K" ~
                int a = ?; // 像`i,a`这种*临时变量* 可以不用写`___`开头;, v) j9 i/ E# C
        }4 r/ O# D; Z; m- R9 g9 I
        . l) P- b  e' ]% Q+ l
} // ___XX9 E3 L. y; e6 F* b% J

7 }7 T+ S1 m# g  Y" A@DELI;
$ x: ~1 u5 }5 S9 h
' ~1 |' D& t5 @' }6 W/ p#Initialize函数, 强制的放到构造函数里#
2 H" D: i. f3 a+ M/ L# ?5 N- {最经典的例子是(建图)' [7 X% C4 n% A: _
) v9 N& j6 ~/ ~0 ~( X5 y9 p- u
Graph( int _points_count_maximum, int _edges_count_maximum){}
0 m( r$ a# f& {6 }void Initialize( int _points_count){}
5 G- ^$ D* Z$ H7 S) C1
# G8 q: U; R% [2
  C2 l4 c- g! h$ e$ B  x这样分来 会导致, 每次使用时 必须是: Graph G( 100005, 200005); G.Initialize( n), 也就是两个代码行 (两个操作, 两个步骤)' i; @# C% R/ V. x0 |7 o  x3 b
一旦忘记手动的调用Initialize函数, 虽然会报警, 那你还需要再去写代码 补上调用这个函数;7 b% {0 |4 M8 t6 z

# j/ q, a9 y* u* M7 _/ O# S& w$ l: Z当我们将Initialize函数, 嵌入到 构造函数 里- `, z0 w0 S; }  u% ^( n

& m+ ]# x- v, \+ B6 f% [& VGraph( int _points_count_maximum, int _edges_count_maximum, int _points_count){' ]) b, |( U# a) @* o- q) F, S* N
        ...0 q% O( a* x* d7 z
        //--% _1 U! i$ G' L. _# v' {( K- A' x: @. |
        Initialize( _points_count);) z- j- L. u0 n9 E2 |  {! t
}- H0 p. k0 B# d" t9 V
void Initialize( int _points_count){}
* N7 L5 f7 J* M, j$ {0 H+ U' |3 w- ^# I- h! ~
注意, Initialize函数和原来是一样的, 只是做了两个事情:- e; C) g0 I+ y1 h0 ~
1 将Initialize函数的参数 接到构造函数参数的后面 (比如, 原来构造函数参数是a,b,c, Initialize函数参数是x,y,z, 那么现在变成构造函数参数变成了a,b,c, x,y,z)
! u6 E! M- w7 l5 T2 在构造函数的最最结尾, 调用Initialize( x, y, z)函数;
; T4 [8 n) ?+ x6 K  B5 Z
5 l, U' i' f  b2 _5 I@DELI;0 z. C1 v, c- n. a7 t+ F

5 t# t0 V2 U( w" F. T#数组长度用函数传参来指定#1 k% r/ U$ N5 S! X, }
& P1 h% ]6 ^+ t
template< int _Maximum>- Y. T9 C. P" Z3 ^5 [; p
class ST{! j/ _, C+ ]8 T) E  i( q# G
        ST(){; C* E6 ~" p# F6 M5 v
                array = new int[ _Maximum];
/ Q2 l% o3 ]" \4 ~9 W        }  O% `# u3 E: S" f" C, c& b
private:8 b. c; c* J! M( R
        int * array;
6 G. i$ `" x( S};
. O$ Q/ d! Q( ]% V$ ]% S, H# D+ d6 u+ {0 s9 X7 r  g
The above code should be replaced to:2 Z; T/ y8 W; f& |! v
% ^' a& S4 ~" Y, G% }
class ST{
/ X% }+ B2 ]0 N7 E        ST( int _maximum)
/ g; o  j2 j8 x* f1 a                        :  A% a  n% B9 P% F
                        maximum( _maximum){3 A" A2 O, O% |# E4 z5 Y1 q  w4 t6 k
                array = new int[ maximum];: Z- G, ^) r5 L) j
        }
9 I0 U  X% f* ]9 {) m% lprivate:
! W+ y# M3 @7 J. H. t" L        int * array;2 V% B8 r, B* ~7 ]+ _
        const int maximum;
2 D2 ~5 [! [: o* s: W% a7 l; ^};
7 }, Z  g- Z9 e/ o) M' J. W% ^& ?, j4 q/ ]  n7 A  X
@DELI;. E6 w1 \+ N+ M
笔记5 W0 I7 X7 h$ j9 j) ~5 `( J
有向无环图DAG
/ T8 R3 l/ A3 B: S最小路径点覆盖
' B+ P3 J: K* H# R1 m4 y//{ @Snippet, `ZuiXiao LuJing DianFuGai (最小路径点覆盖)`8 I/ r+ `# e( r; _* u& t" P
{/ c8 s) d" j0 ^! |( A7 f( _2 Z
    int n = `the points-range in the DAG`;
: e! |2 b. R' e: B# Y2 c8 O! D9 i    //--
( \% F: y2 G' B    BipartiteGraph B( n * 2, `the edges-count in the DAG`);" J  R6 {1 {5 Q
    B.Initialize( n * 2);( b, U8 z# V+ d7 @6 e6 i! `( c/ P5 a
    for( int i = 0; i < n * 2; ++i){
( p7 U4 C" p( F        if( i < n) B.Set_pointBelongingness( i, true);4 a. A9 z- v6 E( x8 X# b" X
        else B.Set_pointBelongingness( i, false);
& {* o; y1 m; ?9 C. k    }
0 g) Q2 Z3 _8 ]" Z! _    for( `s -> t` : all edges in the `DAG`){1 d9 r! a* H7 ~; n0 j+ H
        B.Add_edge( s, t, 0);& U6 B6 c3 W9 r3 m
    }
% Z$ S  T5 Z% n7 S    //--1 n% R7 G7 V/ i2 {" {$ @: N0 a
    Bipartite_MaximalMatch M( &B);' g  `* a/ I# a" _) m
    M.Initialize();
. z4 E7 D' p6 X) j! a1 z    $(n - M.Get_maxMatch()) is the answer;
  z: W0 G5 {6 x/ O- X}
- k3 p7 {: r2 J( n1 z  ?//} @Snippet, `ZuiXiao LuJing DianFuGai (最小路径点覆盖)`! n/ q1 b- Z! W; b, J7 K

( i$ R, g/ W: f$ o1 R: g最小路径重复点覆盖, 最大路径独立集
( h# g) I  T, i4 Z//{ @Snippet, `ZuiXiao LuJing ChongFu DianFuGai (最小路径重复点覆盖)` `ZuiDa LuJing DuLiJi (最大路径独立集)`
$ N, a( Y( o8 r4 a4 p, C{
6 x! G- U4 ~( X+ o& ~, ~$ H+ D    int n = `the points-range in the DAG`;
  U3 D6 Z+ e3 p# x- y4 ~    bool * edges[ @PlaceHolder] = $(edges[a][b] means a edge `a->b` in the DAG`;
' _3 p+ v* I# F1 d$ C1 g0 k    //--2 j/ v  x2 ^. t  c
    $(perform the `Floyd-Boolean` on @Var(edges));, [4 A2 v, v4 K3 c
    //--6 J0 o: t2 s3 y/ h& b
    BipartiteGraph B( n * 2, n * n);# _: B" K8 v/ w8 b& u
    B.Initialize( n * 2);, R) X4 x& p) C. x7 E% y
    for( int i = 0; i < n * 2; ++i){
2 T8 W$ U: u% s8 _7 f5 E2 h        if( i < n) B.Set_pointBelongingness( i, true);; p/ h! d9 G9 {3 c" c4 W# p
        else B.Set_pointBelongingness( i, false);
& U7 |/ T7 S6 f, t2 b. R    }
) [+ V3 W6 u* E& |4 O    for( int a = 0; a < n; ++a){& Q: C) I6 W. r6 B1 H: S
        for( int b = 0; b < n; ++b){
. ]* V1 A" L" D2 R- H: W3 i$ f7 y            if( false == edges[ a][ b]){ continue;}
3 F" B$ k6 O& ^6 Q4 ~            B.Add_edge( a, b + n);9 ?8 ^% u7 ?1 K
        }
" j7 k& \4 e" e0 q    }
( F# M3 l! }* }: ]2 O' L    //--
4 A2 |+ _% K: v$ e( i    Bipartite_MaximalMatch M( &B);
$ ~( [" a$ c" n; E    M.Initialize();$ c3 A& d: b$ d# H
    $(n - M.Get_maxMatch()) is the answer;! u- U) y( Y. A2 Q, u
}7 z# i0 a, j% V
//} @Snippet, `ZuiXiao LuJing ChongFu DianFuGai (最小路径重复点覆盖)` `ZuiDa LuJing DuLiJi (最大路径独立集)`4 P+ @9 {) @- V$ j  V

" t$ G0 r- W0 _" A8 gDAG的终点1 n* O8 H0 K/ f, a+ K5 P
//{ @Snippet, `EndPoints of a DAG`
# t. d9 o2 g" }2 H) R{7 e  v7 B3 F+ k2 j/ W' n6 V
    int n = `the points-range of the DAG`;
; C( h- G. M6 b4 H    int * departure = `int ?[ >= n]`; //< the departure-degree of a point;
; O) t+ j0 X! j$ s7 R' H    memset( departure, 0, sizeof( int) * n);# K& ]1 k0 ~1 A) X# G
    for( `a -> b` : $(all edges in the DAG)){- M$ \* V- t1 g* J
        ++ departure[ a];2 V* N2 d, r" f
    }
, ]6 ^4 R5 Z" f; d3 T) x    for( int i = 0; i < n; ++i){
8 E4 g) i; P; d  W% f$ |  X        if( departure[ i] == 0){
( Z7 k* v4 t* Q0 ^. S0 d( b* t//< `i` is a End-Point in DAG
* ?- h' G. `" o4 Y/ N        }
) q( Z* N8 _8 Z' u, L# S" X    }5 g; D+ G% Y+ _( @# H+ e7 m& w& q
}
9 q" m! w2 b% {0 O- ?9 _//} @Snippet, `EndPoints of a DAG`6 m" L9 ]3 @% I2 H: l& J: r! _: I
% K7 D" X' T" A$ N
DAG的起点
& }+ M. I2 O9 J) \3 b! k8 V, h! z4 a//{ @Snippet, `StartPoints of a DAG`  G/ E; ^# T9 m2 Y
{
+ {4 t1 ^) d+ C& M1 n" [  P    int n = `the points-range of the DAG`;
# ~3 r$ O- R* Q  `; U1 ?    int * incidence = `int ?[ >= n]`; //< the incidence-degree of a point;
1 |+ `( \5 e" ?, K, I. }- u    memset( incidence, 0, sizeof( int) * n);
6 f& [: H3 C# \' r2 g/ u    for( `a -> b` : $(all edges in the DAG)){
0 |2 D7 z6 |8 c+ J        ++ incidence[ b];) b9 n+ v# V0 V0 ]0 f* d
    }
& L9 r( e/ z/ i    for( int i = 0; i < n; ++i){1 }$ j6 C& i& g8 Q
        if( incidence[ i] == 0){
7 P' G# g/ k/ L; d' c$ A2 \! q$ b                //< `i` is a Start-Point in DAG0 Z6 J9 z. Y/ H  c8 t
        }. }! q- U; X6 _
    }8 j$ `6 j( y$ B& Y5 }
}
- {# V9 M0 S9 h3 ^! S//} @Snippet, `StartPoints of a DAG`
3 `# a! b& d8 P/ u+ Q* W! |  m8 D1 a
判断一个图是否为DAG, 求拓扑序
3 f2 L3 B: k+ N" K3 ibool Work(){/ I! G$ i$ x* r2 B! s! z2 F* N' u
//< `1` Check whether a Graph is a DAG; `2` Get TopologySequence;, q8 u8 v6 \4 M! r0 Y' j; ?9 ~
    int points_range = @Unfinished;6 X( c8 i" ^8 R9 J' k
    int * topological_sequence = @Unfinished(an outside array whose length must `>=` @Var(points_range));+ `, p) Z0 T7 |. `/ T7 v* _0 x
    int * incidence = @Unfinished(an outside array whose length must `>=` @Var(points_range));& x2 l0 T7 t4 N9 i0 B& P
    memset( incidence, 0, sizeof( int) * points_range);' _% H! f+ {* u4 Y1 J/ [
    for( `a -> b` : $(all edges in the DAG){  Z6 {9 P# u5 M4 E! g
                ++ incidence[ b];2 t- v/ g2 k6 M9 T1 e
        }% }. M, H, x& v5 a0 D8 G
    int size = 0;; v1 Z* J7 o* @/ R: R
    for( int s = 0; s < points_range; ++s){
7 V2 R8 w4 a# N' ~        if( incidence[ s] == 0){
4 t- T" ]* Z) ~) D. J- O/ S/ ]            topological_sequence[ size] = s;% X; h# m( K3 ?2 D! ^! {9 E
            ++ size;/ k% j1 L. `8 Y( Z  J6 J5 }
        }
& R* |- t9 L% n. E/ t    }1 L2 [1 t0 d% N( y
    int head = 0;- Q& A2 \! r5 g1 [6 U
    while( head < size){
+ V; d+ B" K' N4 G5 K        int cur = topological_sequence[ head];# E2 k5 M" L5 f% F9 P/ k, z
        ++ head;
1 Z( Z+ c  q" n9 M8 l9 L                for( `a` : $(all adjacent-points of `cur`){2 b7 R4 w1 X) v$ D
            -- incidence[ a];
  I4 `( H  C5 W            if( incidence[ a] == 0){
0 l, m; {+ P- M+ g& @- o1 N                    topological_sequence[ size ++] = a;
& C* |& _$ N3 Y            }
9 K5 M. y, N- f  D* i- e# D        }. {- V. ^1 f0 k7 ?2 `- g, M+ ]
    }$ q3 X4 t) M3 w# w- M  ?5 b
    if( size != points_range){+ Y5 w" s( A. G" {
        return false;
, q' x+ R2 L& T7 |9 D3 _0 f    }! c9 y1 f3 |, _$ G
    //>< The answer Topological-Sequence has been stored in @Var(topological_sequence)
* L/ H- H1 @% w3 v* j5 J' _) P% G    return true;4 Z2 W# U! z( N" ^
}1 g9 L; O8 T' t# W
6 V$ H5 q2 R+ i$ t5 U' c2 @( C
图论
& @% U1 E# n! ~, W$ I1 Q- a* }& @/ H/ O2 v最短路) ?( L0 e, W8 c; b: G/ a# E7 K# }
TARJAN8 U. k  H& w/ l% u9 t
无向图-PBCC点双连通分量0 \& x: W( [) g$ K" G; r/ ~( \! d& |
+ 割点8 D. D7 N1 l' Q7 D& i( \
+ {, v9 a# j; A  L' W; }) a
//{ Tarjan_PBCC-Declaration
; N2 V8 K' C: p; @  ~" _$ f3 O7 utemplate< class _Edge_Type>
8 |, r+ I, Q& h5 pclass Tarjan_PBCC{% n+ g& i# K6 D# D# {1 {
public:/ q, ^& t5 V! M3 l9 m% F
    const vector< int> * Pbcc;1 [8 B, Z9 l! o% X+ O* c
    const bool * Is_cutPoint;& C* p5 i' \+ e+ H
    //-- variable ends
% @' i: {8 ]$ P: i    Tarjan_PBCC( const Graph< _Edge_Type> *);
# V+ \( L8 V# U4 e* Y2 K    void Initialize();; I' C6 C7 w" m4 f0 S6 u
    int Get_pbcc_count() const;
: C3 x0 ~. a4 @+ Y: F# ^! wprivate:
; h  h/ z3 U7 U2 ?, Z' S5 f    const Graph< _Edge_Type> * graph;
3 v0 J+ {. f  q9 U- j3 h7 o4 C    int * stack_;7 y3 F0 u9 g+ K5 \" L9 \% r. D, _
    int stack_top;1 q# o1 \: H+ m
    int * dfs_id;+ H5 f& d8 T; T$ d
    int dfs_idCounter;
+ E! K* O* D/ |2 Z    int * low_id;
8 A; `3 u2 e. s. [; V: ~" O+ M    vector< int> * pbcc;9 ~$ k( c3 f. ~! a8 C7 o7 M
    int pbcc_count;
& Y, U1 ~% W9 n6 B    int dfs_startPoint;3 Z% h3 s$ U# R. l4 X) w" U( B
    bool * is_cutPoint;& S( d; X! f5 `" w
    int cutPoint_count;
4 ]$ D. I. w# V% e1 f) g: Y* R0 |    //-- variable ends7 [- ?. a6 \$ t) t6 m
    void dfs( int);
$ n% u4 P6 B& D' Q& S, j4 N/ J};
2 }! g: B6 G' D9 h//} Tarjan_PBCC-Declaration
) `6 a. B, O3 J  }/ ~# m" M
5 ~' z- K0 J- \0 ^$ T$ B//{ Tarjan_PBCC-Implementation7 x3 J' Q, s( `' t$ e3 h
        //{ Variable-Annotation
+ n4 A# n- B! l" W# p8 c" P                //{ @Var(pbcc)
; K! I! J! A  ~# y                // + `pbcc[i]={a1,a2,...}` means that the PBCC with id `i` consists of these points {a1,a2,...}+ W& ~, ~) D, M! S+ ^4 w9 u
                //} @Var(pbcc)
) m, T( b4 d# U$ O& U7 a. I- d' e                //{ @Var(graph)' a7 G5 R6 @0 y" f" T& \! s7 t: T
                // + must be a undirected-graph, i.e., Edge[i] = Edge[i^1]
  P3 `  A. D0 ~                //} @Var(graph)
3 p& _+ s6 l# t; W4 e! z: P9 G! e        //} Variable-Annotation3 r; v4 k2 q5 O+ [% K6 M0 Z* T
template< class _Edge_Type> int Tarjan_PBCC< _Edge_Type>::Get_cutPoint_count() const{ return cutPoint_count;}7 c2 t7 a- v  C: {
template< class _Edge_Type> int Tarjan_PBCC< _Edge_Type>::Get_pbcc_count() const{ return pbcc_count;}
  [, u2 s" h+ t3 `  R/ ktemplate< class _Edge_Type> Tarjan_PBCC< _Edge_Type>::Tarjan_PBCC( const Graph< _Edge_Type> * _graph)6 ]2 Q. ^: U- ?3 ~+ E3 I, t2 [
        :4 z" X$ ~- l) k) S9 ?
        graph( _graph){
" b% I9 n( @* u+ I/ j. F5 S    stack_ = new int[ graph->Get_pointsCountMaximum()];
5 S- x  |, G: K* L    dfs_id = new int[ graph->Get_pointsCountMaximum()];' G" X  S7 ]7 p
    low_id = new int[ graph->Get_pointsCountMaximum()];: \9 T% K5 R9 @$ b3 k: S8 Q) ]
    pbcc = new vector< int>[ graph->Get_pointsCountMaximum()];1 W! I: i1 W. I
    is_cutPoint = new bool[ graph->Get_pointsCountMaximum()];2 Z/ T2 I8 v6 O5 b3 Z$ t& B0 F0 ]
    //--
( \3 Q) E3 L. K  Y    Pbcc = pbcc;# ?4 n9 M# E$ [& W& Z  N' ?) _) a
    Is_cutPoint = is_cutPoint;
7 Q0 `4 v7 U  r6 c9 f}2 Q: e* R# `& p( t, _: I) H
template< class _Edge_Type> void Tarjan_PBCC< _Edge_Type>::Initialize(){
& B7 F, D5 {; N7 c! K* g: r    stack_top = 0;& l; X4 I! L6 Y" i& H4 U% @8 |
    dfs_idCounter = 0;8 s' ]3 T, e0 v5 V7 v) x% t% ]2 A
    pbcc_count = 0;6 K' F* K1 u* [  ]% R1 n
    cutPoint_count = 0;/ V3 n# O- M3 b+ v3 C: p- i, V
    for( int i = 0; i < graph->Get_pointsCount(); ++i){ pbcc[ i].clear();}
. N& I; N7 Z$ J# i! q5 {3 E2 D* s    memset( is_cutPoint, false, sizeof( bool) * graph->Get_pointsCount());
, E" {7 ~1 T) d9 Y. \    memset( dfs_id, -1, sizeof( int) * graph->Get_pointsCount());
8 v$ w  C( \) U& z    for( int i = 0; i < graph->Get_pointsCount(); ++i){+ a* e6 B+ Z8 h: [
        if( -1 == dfs_id[ i]){
  N& A8 D% m, o0 o8 y* \            dfs_startPoint = i;( \9 n) v) k% C
            dfs( i);
8 P2 N! B4 Z; l, U' u  N4 Z- i        }
' \! M1 J* J3 |. m. p    }; y6 e' n: c2 u0 g
}
' Z: Y1 B8 V7 M3 P7 r' i5 W$ S& Qtemplate< class _Edge_Type> void Tarjan_PBCC< _Edge_Type>::dfs( int _cur){! y% W( e! u/ B2 C* D& n1 X' S
    stack_[ stack_top ++] = _cur;  J: Q4 h7 `; ~1 |- `' c* ^
    low_id[ _cur] = dfs_id[ _cur] = dfs_idCounter ++;% V: F4 ~& ]$ g( j
    //--
8 n# |. C" a' q( @- D9 j    int cc_count = 0;7 Z7 ]5 r4 m7 g9 ~1 `
    if( _cur != dfs_startPoint){ ++ cc_count;}
  w$ v5 y# D/ m& q    for( int nex, edge = graph->Head[ _cur]; ~edge; edge = graph->Next[ edge]){
# J' h6 H6 ^9 U; ]) n, Z6 Q        nex = graph->Vertex[ edge];3 ]% f3 E# n4 J% H( ]
        if( -1 == dfs_id[ nex]){
, \2 \9 t9 \' u* \, `            dfs( nex);
& M8 Q/ ]0 T" |) E: o            //>< `low_id[nex]` always `<= dfs_id[_cur]`7 B* U& \( b5 C8 T. P; }7 Z
            if( low_id[ nex] == dfs_id[ _cur]){
2 f  f# ~7 k) z4 `6 z# h5 r% E                ++ cc_count;
) ], M+ B: ?: c( p9 X                if( cc_count >= 2){
4 I9 ^, A( u, z/ F8 D- U                    is_cutPoint[ _cur] = true;9 \. s/ }6 j' K, X- a2 S
                    ++ cutPoint_count;
& o( a* J8 J% ]3 e5 H                    while( true){
- D0 J$ C! N) d% ]; }3 A                        int c = stack_[ stack_top - 1];
" r( |& E# q. \2 A( r; G5 g" d9 `                        -- stack_top;' v0 U0 f  V5 R! k
                        pbcc[ pbcc_count].push_back( c); //< the pbcc_id of `_cur` is not only `pbcc_count` if `_cur` is Cut-Point; i.e., any Non-Cut-Point must belongs to a unique Pbcc, while a point must belongs to `>=2` Pbcc when it is Cut-Point.
+ j, o( R) S1 [/ o8 _  ?4 `                        if( c == nex){ break;}
" ~$ p; Y0 j( W/ g$ H' ]' C" x                    }
9 y0 {) ^+ U0 P                    pbcc[ pbcc_count].push_back( _cur);; C; I; C( G0 r& L
                    //>< `pbcc[ pbcc_count].size()` >= 2
( m  E) k: ^( h! T                    ++ pbcc_count;  N/ D: p) f, ]
                }
7 K. A2 {) f8 m            }
) G1 {7 S. A. }5 C8 b2 ]* V; F# G            low_id[ _cur] = min( low_id[ nex], low_id[ _cur]);
3 J( c3 b, i  ^7 B        }0 ^, V) h* W4 I& ?" D7 q
        else{ //< `nex` must on the `stack` due to the graph is Undirected, ~5 \5 E) n. Q4 _3 r1 F3 h/ L
            low_id[ _cur] = min( dfs_id[ nex], low_id[ _cur]);% E: V: V1 R# Y7 x& {4 C
        }
: D9 p9 k2 `( Q- p$ }0 d    }
# a: N$ M4 |/ X& M    //--
# V/ {4 P  Q3 X* l% W: ]% s& Z    if( _cur == dfs_startPoint){) k2 V# `* l6 q# G5 G, Y
        while( true){2 x& U+ O1 d9 c$ f
            int c = stack_[ stack_top - 1];
% E/ [5 I' |. R, s  O            -- stack_top;
7 z7 I1 m1 H8 B4 V$ ]& F% l            pbcc[ pbcc_count].push_back( c);3 T7 U7 w9 C/ C$ h) V# o* I$ o
            if( c == _cur){ break;}
1 ]! T, W) l+ @        }/ h0 W+ j5 @6 g0 O& R! t. Z
        ++ pbcc_count;
  y1 m: r* i' B; {    }
* s% g0 D; D  ^" w    //>< `cc_count` means the number of Connected-Component when `_cur` was removed from the current Connected-Component (whatever `cur` is Cut-Point or not);
6 @' f; _  b( E% t1 z+ ^}3 r0 a+ ?* t  t) c) D2 M
//} Tarjan_PBCC-Implementation# g) I* e8 B- O1 n* i7 }

. u: n4 `* z, n6 {无向图-EBCC边双连通分量
( Z! q/ ]( G& L+ 桥: R1 n$ Q/ R- _% x) u# {

0 m( L2 j2 h1 H" R: Q& n) x//{ Tarjan_EBCC-Declaration
9 M+ T+ P4 c& I' ]; ?; ntemplate< class _Edge_Type>
# h* G5 b' b9 u/ R) o8 u) qclass Tarjan_EBCC{  Z7 Z! Y) L7 q( d4 U3 a
public:
) J& f5 k" [. w' V- j2 ~    const int * Ebcc_id;4 j* \8 ~/ F+ F1 c
    const int * Ebcc_size;" S" x' W1 J2 ?+ b, a2 l
    //-- variable ends6 n! d$ X- g0 b
    Tarjan_EBCC( const Graph< _Edge_Type> *);; Q0 z2 Q( s5 ?" h. M
    void Initialize();
) F; K4 c  S. k- p9 M    int Get_ebcc_count() const;' {# ^1 z8 a4 A; m/ _
    const Graph< _Edge_Type> * Build_tree() const;8 @' v( O( F0 f* H' I* N) i
private:
5 P1 F" b4 t0 Z. }; M; F9 W    const Graph< _Edge_Type> * graph;/ S# t/ |! r' g; H, c, B6 C% A
    int * stack_;$ F2 a1 X" |  V) w3 U' R
    int stack_top;4 I( r( A" h9 S
    int * dfs_id;
5 f  D3 m  {# V8 a" ]    int * low_id;  n! n7 S" n4 F; E
    int dfs_idCounter;
- @; P- M5 @0 |1 Q& S" j! A2 V# c    int * ebcc_id;, u9 J5 D* }/ A: [. y9 g
    int * ebcc_size;: H. [# ]5 e* }. O
    int ebcc_count;& T# J! x7 l4 l7 n5 E
    //-- variable ends. q- ~- S4 t% T2 j
    void dfs( int, int);) |6 Z) [, [" U
};
1 L2 {# y$ j; z8 t  \8 Y//} Tarjan_EBCC-Declaration0 o# L4 G8 k8 z) h' a" M' C
+ G3 g% [) Z- k  b" y$ G, _
//{ Tarjan_EBCC-Implementation
9 \+ j! @$ N1 p$ v        //{ Variable-Annotation
- f  o8 f9 {2 q8 D# \4 u                //{ @Var(graph)
2 Z+ l4 O$ n9 S                // + must be a undirected-graph, i.e., Edge[i] = Edge[i^1]) j( x+ @" B# {1 N
                //} @Var(graph)
) Q* t0 z& y- {  z1 m8 T5 b                //{ @Var(Ebcc_id), [; o3 |" l/ r- @
                // + `y=Ebcc_id[x]` where `x` is a point of @Var(ptrRef_graph) and `y` belongs to `[0, @Func(Get_ebcc_count)-1]`
5 G0 Q! }' L$ v# C- v                //} @Var(Ebcc_id)% Q" @% V& G+ r& s  C2 d% V; v* W- W
                //{ @Var(Ebcc_size)* ~5 Z9 h* Z' ^/ ~: s. g/ e
                // + `y=Ebcc_size[x]` where `x` belongs to `[0, @Func(Get_ebcc_count)-1]`, the sum of `Ebcc_size[0,1,...]` equals the points-count of @Var(ptrRef_graph)- @9 E2 Y4 v7 |+ u( Y/ }
                //} @Var(Ebcc_size)
" E, G( V/ z' }4 ?6 L! P- o        //} Variable-Annotation
5 N% r0 _5 H5 P' B5 d6 _3 {template< class _Edge_Type> Tarjan_EBCC< _Edge_Type>::Tarjan_EBCC( const Graph< _Edge_Type> * _graph)5 t/ T4 ^# v+ O6 n3 m( i/ Y. g
        :
5 z1 H- s5 P% p        graph( _graph){
% q4 n+ i9 x: s  Z& f: |    stack_ = new int[ graph->Get_pointsCountMaximum()];6 P, c$ n- W% R' p5 h. q' `8 B
    ebcc_id = new int[ graph->Get_pointsCountMaximum()];
. ]; W9 ?4 f4 m4 s- D    ebcc_size = new int[ graph->Get_pointsCountMaximum()];1 ~* G1 }. A% r5 B9 S& L) B" X
    dfs_id = new int[ graph->Get_pointsCountMaximum()];
7 u( r, m" i! [! v    low_id = new int[ graph->Get_pointsCountMaximum()];" R) M' ]1 ~- r
    //--; t3 B, N# r) s
    Ebcc_id = ebcc_id;
! F: ~  Z' L. ^8 t. K& K    Ebcc_size = ebcc_size;% S# k; J; K4 _
}
5 {% V2 m$ Q( ]! u  ~: N  Z  @template< class _Edge_Type> void Tarjan_EBCC< _Edge_Type>::Initialize(){
: b7 {& ]' {% o1 G4 L7 w  W/ z: [    stack_top = 0;
* d! D2 o4 I% b& s    dfs_idCounter= 0;
8 `3 f5 M) t: R2 Y, f. X( E    ebcc_count = 0;
% @) T; x# M2 [    memset( dfs_id, -1, sizeof( int) * graph->Get_pointsCount());& j: p" S$ G) x8 v& |% r
    for( int i = 0; i < graph->Get_pointsCount(); ++i){
8 s7 `* C7 n7 w0 H* u% d1 q7 }        if( -1 == dfs_id[ i]){
. C  ]0 _7 H+ m: S& k9 h! I" L7 G5 ~            dfs( i, -1);
: c( A) j1 n, |7 h$ ?8 x* B        }
  {1 R! [5 N5 |& b1 N, k) O7 k0 b$ F    }
1 h/ X2 n* X9 X( |0 y  U9 R}
6 j5 q8 w, Y" E1 C- I7 l" btemplate< class _Edge_Type> const Graph< _Edge_Type> * Tarjan_EBCC< _Edge_Type>::Build_tree() const{
; P! i1 g6 U  s! S" \5 Q4 ?) E//< + Make sure @Func(Initialize) has been called$ T5 C& K9 ~! ]( X3 @$ y3 F
//< + There is at most one undirected-edge between any two points in the Tree (i.e., @Ret)
' M% d: ]7 i* I6 a8 {* Q, b1 h; N    Graph< _Edge_Type> * Tree = new Graph< _Edge_Type>( ebcc_count, graph->Get_edgesCountMaximum());
: R, [. J& {2 b( O; l    Tree->Initialize( ebcc_count);
; `( k" H8 \' `4 w# z/ y- |% \4 N. {    for( int a, b, i = 0; i < graph->Get_pointsCount(); ++i){
7 \; m7 O  ?* M. j) d' V# y        for( int j, z = graph->Head[ i]; ~z; z = graph->Next[ z]){
( C4 h; y- T# f0 a$ O: y            j = graph->Vertex[ z];
; l5 O( s9 u; d" f$ L& F0 t            a = ebcc_id[ i];
1 O$ j9 R$ x( Y0 W+ v. `# K" }/ Y            b = ebcc_id[ j];
& v( v9 ?$ }: [9 h) G- R            if( a != b){7 G9 @# h9 U  _, ], N
                // Now, there must has no edges between `ebcc_id[ i]` and `ebcc_id[ j]`
1 K2 ?6 D' t3 h4 v7 y                Tree->Add_edge( ebcc_id[ i], ebcc_id[ j], graph->Weight[ z]);
8 \9 C; ~0 N. x% Z5 u$ K/ v7 \            }
; l( U/ G6 C, ?& x        }; J0 k" S% C( M; ?* a: E3 w
    }" B) @! U  G1 P8 e% [
    return Tree;5 z4 r0 b$ ?: ~% j
}" ^8 x6 n8 ^1 q8 d7 s% a
template< class _Edge_Type> void Tarjan_EBCC< _Edge_Type>::dfs( int _cur, int _father_edgeId){
3 Q. _8 v  k; k" ~3 o" e. g    stack_[ stack_top ++] = _cur;
, @0 @" R8 R! e" J8 p% m1 E* G( n    low_id[ _cur] = dfs_id[ _cur] = dfs_idCounter ++;! Y% p) Z. a- l
    //--
1 Q  x. X! Y1 W) A    for( int nex, edge = graph->Head[ _cur]; ~edge; edge = graph->Next[ edge]){
$ h0 g, ?5 u+ S$ O# x. }- `+ W0 Z" K        nex = graph->Vertex[ edge];
5 i6 i, y. d2 t# B/ ]        if( (edge ^ 1) == _father_edgeId){ continue;}
9 v- s4 M6 m( i2 Y  ]- d$ J        if( -1 == dfs_id[ nex]){
) i, c+ ^3 y9 s( v            dfs( nex, edge);
8 _. _( X% ?) B) T% _: X0 `" W            low_id[ _cur] = min( low_id[ nex], low_id[ _cur]);
  W$ N9 v: s  P# B& g: ~        }
3 H2 M$ m# J/ G/ b0 y5 }( D- s        else{& M2 G0 f; J7 H1 \7 Z7 ]3 w% n6 J: H
            low_id[ _cur] = min( dfs_id[ nex], low_id[ _cur]);5 I' ?/ n, }7 h# ^
        }; j4 ]; V3 t0 R, W/ |# O2 S8 z
    }5 E$ U% r1 J6 d
    if( low_id[ _cur] == dfs_id[ _cur]){
8 j1 ?0 E4 O, g$ S        ebcc_size[ ebcc_count] = 0;
! [( z# ]' |: q) u# d        while( true){. P% _, t9 o. t) q
            int c = stack_[ stack_top - 1];
6 I0 V3 T( ?0 A$ p4 W8 i! q9 V            -- stack_top;% U, \( d; d3 _5 Z8 t
            ebcc_id[ c] = ebcc_count;0 l, T( n* B  r9 u$ @$ [
            ++ ebcc_size[ ebcc_count];* n( j; L' R( {" [6 m% [- [" H
            if( c == _cur){ break;}
" l+ I; e+ I1 v4 }: q        }! `+ T9 a" C( |* h! g. M. U/ _
        ++ ebcc_count;
) U: C$ p- J. _0 f% @5 _! [8 [6 I    }/ z! J; @; w; S) c& z2 y
}
# y* h& [& u0 u' D% @9 T//} Tarjan_EBCC-Implementation+ _7 Q$ V' H2 e) x

3 H# i! ?6 W, n6 ISCC有向图强联通分量, Y( d6 X3 T- ^  p, \+ W4 x
//{ Tarjan_SCC( m* _0 I# t7 N+ ~
template< class _Weight_Type>" `! F: O! G) ]8 i! D7 O
class Tarjan_SCC{4 g6 S, F, x( U" y6 m$ p. Y1 ]4 U
public:
! d3 J$ J. q- g1 G: L0 c: z" u, A    const int * Scc_id;0 M# G/ n4 @% Y0 t# o  k& J0 `8 l
    const int * Scc_size;
+ D9 t" u: ?# P9 J% ~% \    //-- variable ends% c; o' w5 U; X( F0 D. t6 v( `8 A
    Tarjan_SCC( const Graph< _Weight_Type> *);
/ p: U& r4 G7 g3 W    void Initialize();
! e/ J/ q! q6 ~    int Get_scc_count() const;
+ p& l2 Z: L$ H3 Z# Q    const Graph< _Weight_Type> * Build_DAG() const;
4 G) _  Q& f7 N( O% i' X0 z& @    const Graph< _Weight_Type> * Build_DAG_uniqueEdges() const;
9 J5 ?- n5 b1 t4 H$ B/ o: Tprivate:, Q( t' z% V3 e! H! N# P
    const Graph< _Weight_Type> * ptrRef_graph;5 m: ~7 x; X8 k/ S, j5 c
    int * ptrNew_queue;$ ]+ a- H7 V# n# T) v4 m! Q* h, L
    int queue_tail;
9 q) b- A$ `& w( q    bool * ptrNew_isInQueue;1 i6 N3 g8 F9 S4 @% f! S
    int dfsOrderId_counter;& @3 _6 G7 c- }9 m9 F7 b8 J
    int * ptrNew_sccId;) s. b: Q# c- b7 J1 I" Z& ]
    int scc_id_counter;2 f' A( i7 a  L+ S$ S9 N8 G
    int * ptrNew_sccSize;
' k% P9 c3 Z& O  z8 U    //-- variable ends1 c- R: [0 K1 \) {: j- p& Q
    void dfs( int);
) `/ s6 d' U2 S1 h};
+ k3 Y; z. J1 E8 z1 ]" Q//{ Variable-Annotation
7 k/ m: p( @; Y( B// + @Var(Scc_id)3 }) W+ r# O' _. q" @4 O, f
// . `y=Scc_id[x]` where `x` is a point of @Var(ptrRef_graph) and `y` belongs to `[0, @Func(Get_scc_count)-1]`" Q6 a$ B8 L6 B1 A# _8 D% V
// + @Var(Scc_size); [  _" B3 Z2 B4 a. H8 z$ `4 x6 U1 T
// . `y=Scc_size[x]` where `x` belongs to `[0, @Func(Get_scc_count)-1]`, the sum of `Scc_size[0,1,...]` equals the points-count of @Var(ptrRef_graph)
& v; |0 V' ?( o" n4 |//} Variable-Annotation
* B4 {, @0 o  ?0 Gtemplate< class _Weight_Type> Tarjan_SCC< _Weight_Type>::Tarjan_SCC( const Graph< _Weight_Type> * _graph)
% x. ]3 d0 Y$ W) `        :
) r) N7 v0 A1 z7 Q9 \/ E- L* b2 w        ptrRef_graph( _graph){
! F  @% @: z0 v4 R9 U0 m( J4 v    ptrNew_queue = new int[ ptrRef_graph->Get_pointsCountMaximum()];
- M( o5 o1 b! H7 l" Z2 f    ptrNew_isInQueue = new bool[ ptrRef_graph->Get_pointsCountMaximum()];
% K* C8 u/ M. z5 a    ptrNew_sccId = new int[ ptrRef_graph->Get_pointsCountMaximum()];
4 |" f3 `9 p: G    ptrNew_sccSize = new int[ ptrRef_graph->Get_pointsCountMaximum()];- D3 X% W! l4 w3 X
    //--( }+ |9 s/ t0 \# G3 ?
    Scc_id = ptrNew_sccId;2 q6 R# Y: ]) Q$ u) w9 ^5 p
    Scc_size = ptrNew_sccSize;
1 c( w3 K5 T2 }. S5 X, j}
% Q& @+ i7 z. @. |8 o" I" z1 gtemplate< class _Weight_Type> void Tarjan_SCC< _Weight_Type>::Initialize(){) v- s, u4 b3 |0 R; {: T6 t
    queue_tail = 0;
  m) \# v) A: X    dfsOrderId_counter = 0;) X. y4 d6 ^/ j/ q( I) D7 M( v
    memset( ptrNew_sccId, -1, sizeof( int) * ptrRef_graph->Get_pointsCount());
. ]8 \& E/ o2 Z    scc_id_counter = 0;
* Z( }' ~$ p# s( }+ a% J    for( int i = 0; i < ptrRef_graph->Get_pointsCount(); ++i){8 x7 ~$ B: P+ v5 N" o; Z
        if( -1 == ptrNew_sccId[ i]){
; L, Y6 Y0 ^" P            dfs( i);. b  h$ Z' G7 j* }4 s# G+ k
        }
9 N' B5 s; G% d  A    }
0 u& a7 `' R& k6 T: q  N}7 B% ~. C/ a6 x) F3 f
template< class _Weight_Type> const Graph< _Weight_Type> * Tarjan_SCC< _Weight_Type>::Build_DAG() const{  h4 N/ h: U# Y: b9 J0 `+ ]
//< + Make sure @Func(Initialize) has been called6 [5 m1 N" A& j# B$ l" |6 ]  [5 i
    Graph< _Weight_Type> * DAG = new Graph< _Weight_Type>( scc_id_counter, ptrRef_graph->Get_edgesCountMaximum());. l5 j( y3 i. {5 N! L& |, V. i6 T. A
    DAG->Initialize( scc_id_counter);
0 W% |+ C2 E& Z4 q: e) e  a+ F    for( int a, b, i = 0; i < ptrRef_graph->Get_pointsCount(); ++i){8 g8 ]+ g, n/ u- R. H3 [' x
        for( int j, z = ptrRef_graph->Head[ i]; ~z; z = ptrRef_graph->Next[ z]){$ {: m0 e/ }2 C  F; }' {
            j = ptrRef_graph->Vertex[ z];
$ C& d8 Z& ?# z9 t% f9 j0 V            a = ptrNew_sccId[ i];, q! }9 [6 I) u7 v
            b = ptrNew_sccId[ j];! G0 T( O! M# W' f
            if( a != b){
/ r6 J* E! q6 W$ J( b                DAG->Add_edge( ptrNew_sccId[ i], ptrNew_sccId[ j], ptrRef_graph->Weight[ z]);9 J! w/ e+ A5 m# h, D2 u1 S
            }
$ s& Z( z& W) f9 T& I. s        }2 Y# T2 k8 t# h9 ?# a4 q6 K7 d
    }
' m/ u: v8 Y  e+ ^+ I4 J, d    return DAG;$ n. @0 V; s) Q1 G% _+ p
}
+ W7 ~  M0 Y- |5 }6 Z( F. T3 htemplate< class _Weight_Type> const Graph< _Weight_Type> * Tarjan_SCC< _Weight_Type>::Build_DAG_uniqueEdges() const{
: c6 i9 N% |7 a  h0 j: t9 t//< + Make sure @Func(Initialize) has been called
0 S2 i1 Z! L5 q( |+ w% i4 D//< + There is at most one edge between any two points in the DAG (i.e., @Ret)  |. v9 k3 }' P  _7 F1 Z2 [
    unordered_set< long long> hash_edges;
6 W7 T% H. ?5 _8 c2 r0 |, i! s+ T    Graph< _Weight_Type> * DAG = new Graph< _Weight_Type>( scc_id_counter, ptrRef_graph->Get_edgesCountMaximum());4 p3 `; T  U; p" y$ P4 ?" u
    DAG->Initialize( scc_id_counter);& B) m% M$ ^, ^1 L  T, m9 E' M
    for( int a, b, i = 0; i < ptrRef_graph->Get_pointsCount(); ++i){8 Q( L2 m0 ?- X9 `  E% N
        for( int j, z = ptrRef_graph->Head[ i]; ~z; z = ptrRef_graph->Next[ z]){
1 x, C9 m. B4 Q* r+ K# t            j = ptrRef_graph->Vertex[ z];
3 C/ \9 L3 Q! K            a = ptrNew_sccId[ i];
3 }, w+ b% B, b6 v% q) {7 W) r            b = ptrNew_sccId[ j];
8 N  v9 O3 G& d, \6 |& i2 g5 h            if( a != b){) r1 |) o& E& C0 D
                long long hash_val = (long long)a * scc_id_counter + b;# J+ p) R* _% k
                if( hash_edges.find( hash_val) != hash_edges.end()){. Z; X1 w4 H2 G* F
                    continue;+ M$ M2 V5 L0 e) P" g- q; \
                }
$ z7 j: c) u  ^' Z6 U# \0 _* g                hash_edges.insert( hash_val);, C0 ]& v$ R# V* X
                DAG->Add_edge( ptrNew_sccId[ i], ptrNew_sccId[ j], ptrRef_graph->Weight[ z]);3 T9 N9 Z' C5 X- F  z, R
            }
$ m1 B8 f; ]" \' B9 y  h4 e        }8 I3 Z0 Q* {& y4 X+ r+ B
    }/ C+ {) ~" W  s- ~; H  E8 m
    return DAG;
" l5 g; `! v: C! _7 Q5 I6 v9 j}" }9 M) n. E' f
template< class _Weight_Type> void Tarjan_SCC< _Weight_Type>::dfs( int _cur){
+ |' _7 `" i# C- B/ o    ptrNew_queue[ queue_tail ++] = _cur;/ r- L, u8 ?/ j6 Z) V5 b6 U
    ptrNew_isInQueue[ _cur] = true;
& D% L! t* q3 G    int current_dfsOrderId = dfsOrderId_counter;
2 `1 L- P0 r1 m1 v    ptrNew_sccId[ _cur] = dfsOrderId_counter ++;8 h8 R4 Y' |$ \9 x
    //--! l7 n' I; q4 p/ u
    for( int nex, i = ptrRef_graph->Head[ _cur]; ~i; i = ptrRef_graph->Next[ i]){3 t$ j6 Q: z$ ]8 t
        nex = ptrRef_graph->Vertex[ i];- w2 l" v/ k9 X$ E
        if( -1 == ptrNew_sccId[ nex]){' h3 U+ N! ^) `
            dfs( nex);3 v9 `5 }' u8 g6 E6 B
        }9 \( n3 Q$ B; i/ \, W/ k
        if( ptrNew_isInQueue[ nex]){
  s. I4 \& _+ O% o% T0 T% d( F            ptrNew_sccId[ _cur] = min( ptrNew_sccId[ nex], ptrNew_sccId[ _cur]);
3 n4 k$ m; o! C' D! t3 n# o        }
( ]  ~, E. Q9 Z# q" [; `, H    }; m9 t8 w, n" U; q" w/ M
    if( ptrNew_sccId[ _cur] == current_dfsOrderId){+ t( C. K& d: y, `
        ptrNew_sccSize[ scc_id_counter] = 0;( T/ N3 R$ D3 z" V! ?
        while( true){( ~$ u! b" x) f" {
            int c = ptrNew_queue[ queue_tail - 1];4 y( q6 E- Z, K8 a  h
            ptrNew_isInQueue[ c] = false;
1 |% ^- P0 Y8 ~6 g+ T            -- queue_tail;
  s" K% M3 e' N" ?- t            ptrNew_sccId[ c] = scc_id_counter;$ ]& y* w* b1 K0 o
            ++ ptrNew_sccSize[ scc_id_counter];* \  B" Y1 M4 k6 J7 S. r
            if( c == _cur){ break;}
, r' @+ J& t* L) b; O- b/ g        }
8 o5 {% X  F' q9 ?( u        ++ scc_id_counter;4 Q! B* Y. |# z& X& e% q$ }0 F2 }6 S+ y
    }
& x6 D# l% z2 k+ c) g}
1 M- o% f5 B! y; S$ y0 L5 j3 \//} Tarjan_SCC
. @& N5 B  L5 n0 \& l4 `  ~5 y4 g* O7 m8 Q. J" @, f
差分约束系统,不等式组9 A! [, c% _4 g1 I% n' y
//{ Minimize_InequalitiesSystem
- ]0 O& d. _0 W. r) q, T1 P  G/ s* O. ytemplate < typename _Edge_Type, typename _Distance_Type>
  G. G  |/ @. S  Nclass Minimize_InequalitiesSystem{
+ t1 H( O# v# I7 L/ {public:
8 Z4 f: p" o- I    const _Distance_Type * Distance;
2 s3 b0 J( E1 `" Q    //-- variable ends
6 x$ M& p5 x2 {) A* _    Minimize_InequalitiesSystem( const Graph_Weighted< _Edge_Type> * _graph)
6 m" B/ w8 `* C4 L            :* }$ u! O% j3 \* e4 R
            ptrRef_graph( _graph){
) E( R( n- ~/ _) {3 s' X        ptr_distance = new _Distance_Type[ ptrRef_graph->Get_pointsCountMaximum()];
/ t( `/ n, m  Y        Distance = ptr_distance;1 D3 U( j9 I5 l" Y' D
        ptr_isInQueue = new bool[ ptrRef_graph->Get_pointsCountMaximum()];. T2 t+ a. x6 m) O" u/ b
        ptr_queue = new int[ ptrRef_graph->Get_pointsCountMaximum() + 1];
+ O% C) s+ A; g+ \5 k' V- |  @        points_range = 0;2 k! n% ~# v5 K2 e( \/ a& m5 Z
        ptrNew_pathLength = new int[ ptrRef_graph->Get_pointsCountMaximum()];' m' Q. b3 g' G: C
        //--. y1 x- {3 h# L2 J8 M
        Initialize();4 h% X& B9 z: P$ z. r. X# @
    }
  |  U8 }7 B+ u+ F4 q/ O8 H    void Initialize(){& ]/ ~. q9 h7 D3 s! O" k7 d
        points_range = ptrRef_graph->Get_pointsCount();6 V9 |7 K+ a' H) D% o: m0 Y) N
    }
3 N  }* a' m. C) M+ b- b! P    bool Work(){/ J+ O0 g" \1 Z" ~2 g  F0 v+ ~
        memset( ptr_distance, 0, sizeof( _Distance_Type) * points_range);1 [, k! y. h9 `8 ~; `
        memset( ptrNew_pathLength, 0, sizeof( int) * points_range);
3 ]0 G  Y  q9 y        for( int i = 0; i < points_range; ++i){
0 j6 A6 c/ L2 u. e            ptr_queue[ i] = i;
  k. K( f8 _, w& p/ e, Q! e( b  C        }
) y  H6 k% u" U- u( j# C        memset( ptr_isInQueue, true, sizeof( bool) * points_range);
: ]3 L1 Y! L/ k& K' a* [' y; z        queue_head = 0;- @5 \+ l, L- e& V6 G9 ]
        queue_tail = points_range;
/ m2 }8 Z0 `8 j* X% G! _  X, \        //--2 z3 u! m6 E2 j8 w6 i3 l5 K
        int cur, nex, edge;
; }8 S4 g+ k, S5 d        while( queue_head != queue_tail){
; E, u- Q$ F/ ~9 P            cur = ptr_queue[ queue_head ++];
- [/ {1 s1 Q) w/ p& c) g            ptr_isInQueue[ cur] = false;* z# W  _! l8 d* H* f; P1 x
            if( queue_head > points_range){ queue_head = 0;}$ _% l  h: e; Z" r2 S8 X
            for( edge = ptrRef_graph->Head[ cur]; ~edge; edge = ptrRef_graph->Next[ edge]){. p8 `' H. |5 P5 A
                nex = ptrRef_graph->Vertex[ edge];
0 I5 Y/ z% z; I" t# E% E- H3 E                if( ptr_distance[ cur] + ptrRef_graph->Weight[ edge] > ptr_distance[ nex]){: @. v( A+ ~5 C8 B; Q" t
                    ptrNew_pathLength[ nex] = ptrNew_pathLength[ cur] + 1;
/ H3 Y7 r8 v: K( i( I& k9 }5 k                    if( ptrNew_pathLength[ nex] >= points_range){( [9 k7 G. G( j- y
                        return false;
9 C2 ?3 d$ y7 H) N  W: b- @, U                    }0 G: `! L! f  o  o; _0 ?+ _
                    ptr_distance[ nex] = ptr_distance[ cur] + ptrRef_graph->Weight[ edge];
% q2 @' x6 O9 K                    if( false == ptr_isInQueue[ nex]){% L7 V6 ~# `1 e
                        ptr_isInQueue[ nex] = true;! u" I/ C6 E2 ~
                        ptr_queue[ queue_tail ++] = nex;
4 P+ ^7 w: X% ?- h' V2 i                        if( queue_tail > points_range){ queue_tail = 0;}
6 |$ r  W# k: z( r9 ]! [7 F$ H                    }
6 K" e- y6 h% f+ h4 B/ E/ G6 d                }
7 u7 n- O: f( ]. l            }) A$ A. Y5 v, v: ?0 o: ]6 L
        }1 C8 ^. r* D0 ?2 w
        return true;
7 ]( Y8 p* L# q2 Q8 [8 t    }
8 q5 q. m% X8 ?# ~4 T' M7 yprivate:& u; z5 C( v- O. x* @0 Q
    const Graph_Weighted< _Edge_Type> * ptrRef_graph;6 w+ W4 E$ M* M) k$ X
    int points_range;
2 r4 Z) x0 B. _! X    _Distance_Type * ptr_distance;5 A& u6 _; c4 S) h6 U
    bool * ptr_isInQueue;% k2 B! c$ X: z
    int * ptr_queue;
' I1 Z5 u+ Z! W* a) f; h2 i1 ?    int queue_head, queue_tail;  G$ P! A$ N# v# L0 \
    int * ptrNew_pathLength;
. G5 t, P$ |8 U/ j' q};
/ z6 E$ d/ M, j/ |, ?2 T) s//} Minimize_InequalitiesSystem% ?/ ?: ~8 O' q1 ]; J
, W8 H0 q, ~$ M2 k+ O
Caution
8 |$ ]* H1 ^5 Q' i- @. V* c' D: w# Z2 T2 F
`+` You should never modify the source-code of @Func( Work), otherwise, it means your algorithm must be erroneous.
, [" T* d% A/ C% C  u5 r2 f0 B1
0 v1 {' q" S7 d! C( [6 {Annotation2 R0 [' r8 X  R2 b6 K6 _
- H; j- p( u& {: X( e1 `  m0 }
`+` @Func( Work)! \8 T% a0 a+ S) h( E
`1` `@Ret = true` means the Inequality-System is Consistent, otherwise it is Inconsistent (No-Solution).; {- f0 [" O3 i3 H. l! e5 \
`2` The effect of this function (if @Ret is true) is calculate the minimal-value for every variable (point) $xi$ Under-The-Condition-Of-All-Varible-Must-Be-`>=0`;
% K/ x: V. O5 \/ f6 G6 m$ u& l% U`.` In other words, under the premise `all variables xi >= 0`, minimize every variable and also satisfies all relations (i.e., the graph)
' U. T! ~- z* s' x/ \, [1 P# f( m9 @3 g
2 n& I- E) F3 X6 c. B$ W`+` @Var( ptrRef_graph)
/ c$ e. D) Y# _" _0 m( \`.` A edge `x -> y` with `w` muse always means a inequality `x + w <= y` where `x,y` are both variables and `w` is a constant.. l. a2 F/ b& v+ F

# o' n% k4 ]$ U) e数论% N3 b. ^2 e) ^1 V! s$ Z" g
矩阵乘法( Z7 a* c3 Q5 u2 V2 O+ G
//{ MatrixMultiplication-Declaration
: S+ ^6 l4 D+ }4 Xtemplate< class _Type, int _MaximumLength>
/ w# u7 S. g# A5 z3 O% B0 Eclass MatrixMultiplication{8 U  r. L8 A; ^5 H# @+ y3 C
public:
# M+ l7 ]( j1 P, `5 k    MatrixMultiplication( _Type);- u4 V" L6 r9 s  Y+ c
    void Initialize( int, _Type (*)[ _MaximumLength], const _Type (*)[ _MaximumLength], const _Type (*)[ _MaximumLength][ _MaximumLength], long long);
# {2 `: }. K6 C- j2 H$ i: b4 Yprivate:, F3 m+ J& t. J7 ^) D  L
    _Type modulus;* [, r3 x0 A- q; T3 b: Z5 Y) j, `
    int length;0 H0 d5 m) l% d- |
    _Type factor[ _MaximumLength][ _MaximumLength];$ P2 i# n/ K% C# q% r6 R8 ~
    _Type answer[ _MaximumLength][ _MaximumLength];
2 ?$ D8 m! |9 H2 k8 ^+ a    _Type temp[ _MaximumLength][ _MaximumLength];
+ \; \' W, u$ G8 V& Z& |- E    //-- variable ends
, T! l9 j2 z8 G0 e( a  G3 k( J    void matrix_multiplication( _Type (*)[ _MaximumLength][ _MaximumLength], const _Type (*)[ _MaximumLength][ _MaximumLength], const _Type (*)[ _MaximumLength][ _MaximumLength]);
% f- w; ?- T6 `4 n$ X};
  m& C$ P- v! N9 T8 J: l//} MatrixMultiplication-Declaration
. i6 E+ u# u/ ]$ t4 Y0 i8 d
/ Z+ P- N- l1 n* Y  |//{ MatrixMultiplication-Implementation
! v( P6 g' g9 itemplate< class _Type, int _MaximumLength> MatrixMultiplication< _Type, _MaximumLength>::MatrixMultiplication( _Type _modulus)
% l+ y2 |' k. j$ _        :
/ Z3 w) h) X9 ~& M, K3 A& O4 }4 q        modulus( _modulus){
3 \% ~$ a0 R3 o. p/ Z( j8 Y  k" o}# X  c& D& O# A5 H& r( H& h8 C) x4 C
template< class _Type, int _MaximumLength> void MatrixMultiplication< _Type, _MaximumLength>::Initialize( int _length, _Type (* _result)[ _MaximumLength], const _Type (* _dp)[ _MaximumLength], const _Type (* _factor)[ _MaximumLength][ _MaximumLength], long long _k){
, o: u% ~$ P2 A4 p" v2 W//<
& F: E0 }, i; j4 V// @Brief
; B# G) R& D$ l2 T// . `result = dp * (factor ^ k)`;
7 `9 `5 F+ c1 t; k0 E' _9 i! ]. Q// @Warning+ r2 o- `/ I# D- G
// . Make sure the data of `dp` is `dp[0, ..., _length)`, the data of `_factor` is `[ (0,0) -> (_length-1, _length-1) ]`;
& R' ?: X% m% I8 o7 {2 ?! {9 h( e    ASSERT_( _k >= 0);
! ?' J. E9 _0 L. g, m    ASSERT_( _length <= _MaximumLength);0 Z5 f, u: e) E  ^. c+ M) O
    //----
( _* I4 {( V9 n    length = _length;/ \' M. w1 ~& c: ], u( L0 W
    //--+ A; Q9 e' z2 m
    memset( answer, 0, sizeof( answer));* N# _2 O( F1 Y( O$ H; B0 o
    for( int i = 0; i < length; ++i){2 d3 E* \& C6 F- U6 q7 t
        answer[ 0][ i] = (* _dp)[ i] % modulus;  if( answer[ 0][ i] < 0){ answer[ 0][ i] += modulus;}
5 Z9 j% J$ O1 G) B    }
: ?$ K& M. @0 `3 }    for( int i = 0; i < length; ++i){
( r4 m! p- l% U" e$ q2 j$ B        for( int j = 0; j < length; ++j){0 @4 c- e# H& i3 o) T! t5 N- p( ?
            factor[ i][ j] = (* _factor)[ i][ j] % modulus;  if( factor[ i][ j] < 0){ factor[ i][ j] += modulus;}
, ]: O2 O: l0 h        }) d; r0 D! W2 b/ T# Q" k( e' `
    }5 B! b1 ?" q( U& P9 q7 H; n
    //--+ k- T% q# L2 T6 E; n5 O' Q1 V- V
    while( _k > 0){! d0 E5 i+ t4 \( d, a# k
        if( _k & 1){- L# Q; j+ C5 \% n* u" q  E
            matrix_multiplication( &answer, &answer, &factor);* j- y( t6 U% x9 b9 K
        }
( l* j# j+ g) I. W( w6 i' ^        _k >>= 1;
/ d4 q& k# \  Y1 K: [6 n# o3 J        matrix_multiplication( &factor, &factor, &factor);
: D5 o" R) s4 ?    }. O; U  {1 k9 O
    //--
' T5 v; ?$ B7 p. e+ B+ W% s9 i- v# t    memcpy( _result, answer[ 0], sizeof( _Type) * length); // the address of `_result` equals to the address of its first-element;) Z$ `2 n+ G# u9 q# N) m
}" Z; a7 j/ G1 L+ g; j
template< class _Type, int _MaximumLength> void MatrixMultiplication< _Type, _MaximumLength>::matrix_multiplication( _Type ( * _result)[ _MaximumLength][ _MaximumLength], const _Type (* _a)[ _MaximumLength][ _MaximumLength], const _Type (* _b)[ _MaximumLength][ _MaximumLength]){; I5 ]7 ?4 @9 i6 R( t9 D7 F% Q
//<; X7 a* x. k5 _8 b% D. \. _# y
// @Brief* r6 L3 l! ^5 E7 A& T0 C$ r# n5 W
// . `result = a * b`;
: r/ @7 @  N5 ^# `6 [, J3 [4 w) Y8 ^, A    for( int i = 0; i < length; ++i){
- F4 ~6 M0 _4 j* {' h5 s# H        for( int j = 0; j < length; ++j){! M$ O" ?2 e( T# ]
            //>> Cuz `result` maybe equals to `a/b`, you need store the result to `temp` not `result`;, J/ {1 M8 O% C
            temp[ i][ j] = 0;5 [1 Z; H/ q+ `
            for( int z = 0; z < length; ++z){
6 ]3 [8 s2 ^' k7 F  B1 d                temp[ i][ j] += (long long)((* _a)[ i][ z]) * (* _b)[ z][ j] % modulus;  if( temp[ i][ j] >= modulus){ temp[ i][ j] -= modulus;}8 Y0 P! i- _. C: g7 X  b$ K
            }* c' a6 H3 _5 ~( B/ G- H
        }: _; ^1 k' {0 A3 g
    }9 h- S6 V; s$ i% k0 V( A% C
    memcpy( _result, temp, sizeof( temp));9 {/ Z, @+ M) D- ?% R1 Z" p
}" n- u6 d* h% ], L/ L, C
//} MatrixMultiplication-Implementation
. l0 A. x% @( a1 b6 c) C6 W, U, T0 \9 r% m0 e9 t8 g5 y& L
@Delimiter
+ ^. i( v2 h  _/ f! t+ f- p$ C" S: Q
- G. {$ h* n, F0 d5 `6 [* L示例6 E* H$ ?2 b1 B- |8 X" A

7 n2 u( n& i, w! pint Dp[ 4] = {1, 2, 2, 1};2 K/ b0 C! M# z, a3 o
int A[ 4][ 4] = {{0,1,0,0}, {1,1,1,0}, {0,0,1,1}, {0,0,0,1}};; D' M5 X) ~+ J8 k) K9 [9 b% B6 F) I
MatrixMultiplication< int, 4> Mat( M);2 z8 m6 ~5 o0 G0 U
Mat.Initialize( 4, &Dp, &Dp, &A, N - 2);
6 e" j2 U) `  a& i" c. e8 k) n+ k
long long ans = (long long)Dp[ 2] * N % M - Dp[ 3];8 {0 w. J3 v$ B6 R/ U2 [! |
cout<< ans;
" `# J- E' B$ |7 u7 H) g1: L$ A  c% ~( `
2
8 i  e" C$ ^6 @30 `+ }% w! t! j4 w( |
4
6 y3 _! z; q8 f; h2 W& Z5
& J5 Q/ W1 \1 g, F+ O6
% ^/ t: ?/ o# ^1 z' V7! Z& N8 q3 ~$ a' j* _1 }
中国剩余定理
7 w/ y0 {2 C  s" ^. V% \- s7 ~朴素 CRT
$ H+ G# f' e; A  A( d//{ CRT-Declaration* U! _3 X1 n) q3 O4 X" c
template< class _Type> pair< long long, long long> CRT( int, const pair< _Type, _Type> *);
2 t, s! G% p" [- `8 D//} CRT-Declaration
9 m) R% ~+ ]* v; Q: n6 z- k6 v- }% B/ E) j, `
//{ CRT-Implementation5 V  q& J# a; p; \2 b! `
template< class _Type> pair< long long, long long> CRT( int _n, const pair< _Type, _Type> * _arr){' @% k1 D3 [. p1 o, h  ?
//<
1 C8 b( n3 A+ `8 W" M* ?// @Brief
7 _5 L8 }! B+ q* B* o5 {% X5 M// . Solve the system of `n` Congruence-Equations represented by `arr` (i.e., `? = arr[i].first (% arr[i].second)`);4 p# [; b' B. }3 X
//   . Once all `arr[?].second` are Pairwise-Coprime, this system must be Solvable (and Infinite-Solutions);8 w; ?+ a' A, @  P- G/ W
//   . @Define( `(a,m)` = @Return), `a` must in the range [0, m), and the Solutons are $a + kk * m, \forall kk \in \Z$;; I, B8 A( `# Y8 W
// @Warning
; v$ N# c. y% m' J3 e; K// . Make sure all `arr[?].second` must be Pairwise-Coprime;
( v& `& e  b/ I// . Make sure the Product of all `arr[?].second` in the range `long long`;. e7 K: h* z2 H
// @TimeCost
; e+ r8 h+ {' k. }3 V// . $n * 60$;
  g, Z: q  i' n/ k- p    long long M = 1;
. n$ v: g; D3 t% H: b7 |  f2 R1 b' ~    for( int i = 0; i < _n; ++i){: F0 e7 p7 c, X8 F4 e. C
        ASSERT_( _arr[ i].second >= 1);3 }( z0 f3 Y2 M4 L
        M *= _arr[ i].second;
* S) f0 ~9 U/ r; t    }
' n8 X- n  |5 b    long long answer = 0;
, a* N1 P" e+ b& ~    for( int i = 0; i < _n; ++i){- q0 Q5 M* @. |# j# x
        _Type a = _arr[ i].first % _arr[ i].second;  if( a < 0){ a += _arr[ i].second;}
2 ~9 t: r1 X/ N% S  C$ i; F. R        long long m = M / _arr[ i].second;
6 E) f9 N6 g* W5 ~        pair< bool, pair< _Type, _Type> > ret = LCE_BezoutE< long long>( m, 1, _arr[ i].second); // m * `ret.second` = 1 (% _arr[ i].second);5 M2 i7 y0 t7 w0 Y# N# u( h: c2 }
        ASSERT_( ret.first); // All `arr.second` are not Pairwise-Coprime which rebels the Premise-Of-This-Algorithm (See @Warning);' K6 X+ I* k- h
        answer = (answer + (long long)a * m % M * ret.second.first % M) % M;
! Y, |) F4 I# g    }
; n# ]: w7 R1 e2 |& M    return {answer, M};% h  G) w  f, Z5 u) K
}
% H* P3 D. L* \( ~5 @& U//} CRT-Implementation
0 D& l4 e# c! _3 v8 _- m
4 O$ i8 S+ e/ \: P6 G拓展 CRT_EX
; s! u8 c% h4 V2 D8 C//{ CRT_EX-Declatation
# w) f+ o. _0 O5 j+ d# Wtemplate< class _Type> pair< bool, pair< long long, long long> > CRT_EX( int, const pair< _Type, _Type> *);
) U5 ]$ H3 I, r//} CRT_EX-Declatation; z& A3 Z7 @4 k, `' o+ E

/ i& y- F# ?7 p! t//{ CRT_EX-Implementation
' q, ~% `' l3 O) O1 }8 Rtemplate< class _Type> pair< bool, pair< long long, long long> > CRT_EX( int _n, const pair< _Type, _Type> * _arr){- T, Y% `& |6 }% {
//<
* M0 k- P4 s0 n: S/ ?7 Z9 x// @Brief
1 W5 x% q. U- n// . Solve the system of `n` Congruence-Equations represented by `arr` (i.e., `? = arr[i].first (% arr[i].second)`);( e* C& K' \) r8 v: c2 X. ^6 _
//   . @Define( `(r1, (r2,r3))` = @Return);$ g  E% a/ `' n, h" U
//     0( r1=false): There is No-Solution;( G8 t! M. q9 l6 i- O
//     1( ELSE): The Solutons are `r2 + kk * r3, $\forall kk \in \Z$`, and `r2` must in the range [0, r3);
0 o! e0 ?1 y7 z7 v7 n/ W//   . All `arr[?].second` maybe not Pairwise-Coprime (which differs from `CRT`);) T" {2 o: I  `
// @Warning/ p! f) b1 c5 C# Q- C/ Y* X
// . Make sure the LCM (Least-Common-Multiple) of all `arr[?].second` in the range `long long`;" |# C5 M) c6 W  m3 ^9 o; z( ]
// @TimeCost" G# F6 f6 g; k. j( y
// . $n * 60$;. J+ ~3 a/ m/ N- n: V* w
    pair< bool, pair< long long, long long> > answer;
5 _' a/ r* n2 Z" E7 [    long long A, M;9 e9 I, j2 w$ g6 I6 j2 K7 X
    for( int i = 0; i < _n; ++i){
2 t2 J1 D7 Z/ q6 N        _Type a = _arr[ i].first;
6 d$ P( q1 l7 n4 p; e# l        a %= _arr[ i].second;  if( a < 0){ a += _arr[ i].second;}
0 d' z- A8 G. ~5 I; \        //--) J4 p8 @, U; `5 {3 o
        if( i == 0){" a) P2 @5 W( M  X$ b+ @) v0 {7 b
            A = a, M = _arr[ i].second;3 `$ i2 P1 G  B, w% ^
            continue;# S' j' B" K0 Y' \% _  o0 `( ~; \
        }* `) v1 [, M- @. h( b4 v5 x
        pair< bool, pair< _Type, _Type> > ret = LCE_BezoutE< long long>( M, a - A, _arr[ i].second);
, T6 e8 Y! T) G) V8 ]7 b: o+ q% f        if( false == ret.first){
& E) }6 U7 }) n3 c: v1 J# c  ~) P7 z            answer.first = false;6 t. a2 N- q& n  w
            return answer;. C, m) I) z" I8 P/ _3 I
        }, r. `. w( A! i3 d
        _Type gcd = _arr[ i].second / ret.second.second;  if( gcd < 0){ gcd = -gcd;} // The GCD of `M` and `_arr[i].second`;
, G+ c& I8 `: ~        long long new_M = M / gcd * _arr[ i].second; // LCM; C9 P- ~/ w) g, E$ k
        A = (A + ret.second.first * M % new_M) % new_M;0 |1 J' `: |7 Y0 E( P6 Y
        M = new_M;: A+ D% u* L9 J" ?2 J2 f/ Z
    }" h/ [; x5 `5 ]8 c! ^0 d/ ^
    answer.first = true;, J% I  B$ \" O* M. j4 m8 m, G
    answer.second.first = A;, Z2 n5 H" e3 g8 P. S* K2 N
    answer.second.second = M;( s. u% A! P) b) w3 n
    return answer;; j' N7 M# V8 c* M+ i
}
+ M  A3 g  x3 t- @//} CRT_EX-Implementation
! _3 s- C" m7 z6 r1
8 O* N1 f+ `$ W裴蜀方程 BezoutE( o' K3 ~+ o$ w7 W) v
//{ BezoutE-Declaration
- {& [; ?; T3 Jtemplate< class _Type> pair< bool, pair< pair< long long, _Type>, pair< long long, _Type> > > BezoutE( _Type _a, _Type _b, _Type _c);
3 h  V8 y  X8 Z/ [! r+ G) N//} BezoutE-Declaration
- O$ A4 Z3 V, W: w5 K1 O) U+ U" [( m. t' o& i
//{ BezoutE-Implementation
2 J. I$ Q$ p# _! Ytemplate< class _Type> pair< _Type, pair< long long, long long> > BezoutE_extendedGCD( _Type _a, _Type _b){6 J* A9 B; Q2 _& \0 [+ q* P; M+ s
//<
  h8 r; Q. W. ^3 L! o$ [! j7 F2 T// @Private
& r: G( A% n& m6 e// @Warning
& I0 a: e1 V7 y" r/ h0 W$ T. O1 }0 r3 t// . Make sure `a,b >= 0`, Not-Both-Be-`0`;* h2 t) e* k" Q( t5 L
    if( _b == 0){
, K' M. Y, i' x$ H1 y- [        return {_a, {1, 0}};
  H) t( v6 @& C2 x) l5 x$ n/ x9 d    }( [0 \4 d" k, M! }/ w" r8 X
    auto pre = BezoutE_extendedGCD( _b, _a % _b);
6 z& s, V0 T% ~3 Y    auto xp = pre.second.first;
. \/ s" h* F4 z  I* C    auto yp = pre.second.second;
8 _' {( Q5 m8 L+ [    return {pre.first, {yp, xp - yp * ( _a / _b)}};
: F# j0 z9 d( |; r5 w6 I+ Q};
, n  B  |! Q4 w6 ytemplate< class _Type> pair< bool, pair< pair< long long, _Type>, pair< long long, _Type> > > BezoutE( _Type _a, _Type _b, _Type _c){$ S9 W7 |" P4 L3 R' ?2 T: v
//<
7 W0 y  K$ F1 u! N8 e// @Brief
( q5 X' Z7 b  w; n& j3 Y// . Solve the equation `xx * a + yy * b = c`, @Define( `(r1, ((a1,m1), (a2,m2)))` = @Return)`;! T- J2 r0 e) U9 |' z. G6 `
//   0( r1=false): There is no Solution;  M- E: J0 V0 [6 y) ]+ g
//   1( ELSE): The General-Solutions are `(a1 + k * m1, a2 - k * m2) $\forall k \in \Z$`;' X2 r5 q0 d9 ^. T, N
// @TimeCost8 j# q) W- K! j- e2 m
// . $\ln(a)$;
7 N& n! `3 h4 I// @Warning
* |4 d. {- a9 x// . Make sure `a != 0`, `b != 0`;
/ o. W8 i: R+ \4 E9 K& J6 A5 b% A    ASSERT_( (_a != 0) && (_b != 0));
- A8 k2 j& Z3 B    pair< bool, pair< pair< long long, _Type>, pair< long long, _Type> > > answer;
  J& v2 M8 W, l+ B5 Z    bool neg_a = false, neg_b = false;) d" e9 A' n4 `7 W2 ?
    if( _a < 0){ neg_a = true;  _a = -_a;} // `x * a + y * b = c` -> `(-x) * (-a) + y * b = c`;
! t, ]4 U+ J4 E# t5 Q7 q3 J; d    if( _b < 0){ neg_b = true;  _b = -_b;} // `x * a + y * b = c` -> `x * a + (-y) * (-b) = c`;& f0 F! L( X6 Y5 B1 l/ D
    //--
' j4 c$ v+ k0 B$ ?/ j! g. @1 b    pair< _Type, pair< long long, long long> > ret = BezoutE_extendedGCD( _a, _b);
* H7 F' S) {% ^8 H2 w' S  @  @    if( _c % ret.first != 0){
+ x) N& R( o# L        answer.first = false;
" o  B7 ^9 R6 k* g        return answer;$ }0 W2 I0 l/ |3 w; e. `* k5 @% n; W
    }
) {8 z6 g9 {" T2 ?# g    answer.first = true;
0 I5 i2 o. h1 t% Z+ `    answer.second.first.first = ret.second.first * (_c / ret.first);( {$ d$ }, g6 \, b' K
    answer.second.first.second = _b / ret.first;2 H$ d. `! f" K, c
    answer.second.second.first = ret.second.second * (_c / ret.first);! T1 f% o% }1 p) D
    answer.second.second.second = _a / ret.first;& w' e9 s( v# W4 q6 m  q
    if( neg_a){ answer.second.first.first = -answer.second.first.first;}5 B& u1 E0 I/ {
    if( neg_b){ answer.second.second.first = -answer.second.second.first;}
: x# M# H! s/ m! u" g$ u& W    return answer;( Y  z% D. o, c* E* o
}
  S0 [! m* E& x) ~' e: s/ O//} BezoutE-Implementation
- f, ?9 N* L$ p% q8 y' f0 {2 m0 ?
: c$ p8 R/ L5 I  O* V6 H5 t' a6 m线性同余方程 LCE% O+ l8 G+ D  M7 v7 i7 f9 G) p
裴蜀方程法 LCE_BezoutE
+ \! I2 D/ z" K3 ~# m; k//{ LCE_BezoutE-Declaration
/ q, m3 C' Y/ e: h! B! _template< class _Type> pair< bool, pair< _Type, _Type> > LCE_BezoutE( _Type _a, _Type _b, _Type _mod);0 |+ U9 r$ _! F3 O1 E3 u) ~0 R, m
//} LCE_BezoutE-Declaration' i% H; b: d" E5 f" }" C2 h( o

* ~: y- G% _# c! f//{ LCE_BezoutE-Implementation  J5 ]/ E% `) X. f' I5 w( @0 T
template< class _Type> pair< bool, pair< _Type, _Type> > LCE_BezoutE( _Type _a, _Type _b, _Type _mod){
8 b  J* Y& P* L# n//<; \6 S+ k/ a$ B7 ^; `
// @Brief' U. m$ {2 p6 Y# i! z
// . Solve the Congruen-Equation `a * ? = b (% mod)` where `?` is @Return; @Define( `(r1, (a1,m1))` = @Return);  `( L: _; p) [$ t8 x& w
//   0( r1=false): There is No-Solution;# V$ N# v" }( s% T8 b' b
//   1( ELSE): The General-Solutions are `a1 + k * m1, $\forall k \in \Z$`, and `a1` always in the range [0, m);
9 t" L6 o) |2 W* {// @TimeCost
3 V- q* e9 \1 h// . $\ln(_a)$;, v% [. a5 t" U4 R' F, [# w* ^
    ASSERT_( _mod >= 1);
4 @$ Z; M! Y) v    pair< bool, pair< _Type, _Type> > answer;
' Y* l5 v  Q* ]7 x7 v$ w8 a) G9 P    _a %= _mod;  if( _a < 0){ _a += _mod;}8 h9 M0 a) C9 K" S1 t7 @
    _b %= _mod;  if( _b < 0){ _b += _mod;}
0 s+ I6 [1 H1 \0 a6 x1 l# U    if( _a == 0){
  s0 J& o  ?0 n% J3 Y6 M6 j        if( _b == 0){& C$ n. }4 p: O- v% n
            answer.first = true;
8 v0 s# K( A; S) I            answer.second.first = 0;
9 Q2 v3 v9 V! N' q            answer.second.second = 1;/ d! d7 w6 u/ ^( ]8 v6 j- j- {( }  y
            return answer;+ G0 ^" h6 O$ m# H
        }
! _) p2 p1 @) \        else{
( l( d$ Z: v1 f6 O. `3 l! I! H            answer.first = false;
! y0 y* S4 G0 S3 X- ?            return answer;5 l7 H) @6 K+ r; x( D4 l, [6 Q! q9 t
        }; }1 H$ }: u8 z; B* `6 t  d& r
    }
/ t! q3 g* M% i# Q) k* b. ^    _Type gcd = GCD< _Type>( _a, _mod);
4 }5 t  P4 w' P# `# j' L( _    pair< bool, pair< pair< long long, _Type>, pair< long long, _Type> > > ret = BezoutE< _Type>( _a, _mod, gcd);
5 i) d$ n( [- O; G) ~    ASSERT_( ret.first);7 C& Y) z& e9 ~; k) F
    if( _b % gcd != 0){! S+ h5 R2 Z% P5 L3 N
        answer.first = false;
- d4 q/ K7 w& `3 p5 ~- r" T        return answer;  D, V# v; z( D9 T; U/ C
    }5 v7 W$ i, y: ?, }4 _
    answer.second.second = _mod / gcd;
; _8 o! I. Z) ~    answer.second.first = Binary_Multiplication< _Type>( ret.second.first.first, _b / gcd, answer.second.second);) q: l! Q" i2 `  N) c
    answer.first = true;
* ^8 E3 v% }6 s* o    return answer;
2 h% h# R; z7 F2 q' r& c% ]}/ r- W: M4 M$ S1 S. S$ A
//} LCE_BezoutE-Implementation
3 V1 s$ V0 f' F, N0 i! S- D$ t7 o/ H
高斯消元线性方程组( [& G- j& l3 g0 X- X) ^2 a
//{ Gaussian elimination' ]  ]7 g- I: x
double Aug[ 105][ 105]; //< @Abbr( augmented matrix)( j/ t% [' s8 C' C# U* }
int Gaussian_elimination( int _m, int _n){3 J( m& S! e1 u7 k3 o) l
//< @Par( _m): the number of equations
1 U1 D6 x& m: [3 X' v/ ]//< @Par( _n): the number of variables
- I: U. V. ~0 a# F3 t+ g, p//< @Return: (0 is unique solution), (1 is infinitely many), (-1 is no solution)
6 y) G" Q! y$ n9 e. w0 d2 w! \% N    int rank = 0;2 x0 u! V% p6 ?; d- Y
    for( int col = 0; ( col < _n) && ( rank < _m); ++col){
  P) K2 s$ t2 c        int max_row = rank;! e4 ~% I& b" u( d+ q
        for( int row = rank + 1; row < _m; ++row){8 R" c0 z* b& w  o2 R/ k: ~; k# u& F
            if( fabs( Aug[ row][ col]) > fabs( Aug[ max_row][ col])){- A. r2 H9 k* q. k0 H3 T/ ?
                max_row = row;
3 o% v$ E* V/ R' U" J. b            }
, e  @  W9 ^6 W" g* L3 K- |4 V        }
  u0 j% d- f; J1 I/ g# j5 M        if( 0 == Db_cmp( fabs( Aug[ max_row][ col]), 0, Epsilon)){
* {( ~2 X8 I# W4 x3 O9 P& R            //* either no solution, or infinitely many.
0 n& G* |6 }' U$ V, @' w            continue;
# {, r2 G: ^% B9 `% Z$ a& Z; b        }
8 ?  C: {' N0 [$ e! t        //{ swap two rows
! }$ \6 p; M2 g/ V. v4 m/ C* G        for( int c = 0; c < _n + 1; ++c){; Z; G# c% u+ K9 b; z
            swap( Aug[ max_row][ c], Aug[ rank][ c]);; m4 [# j. V, G5 v
        }" |7 |) I1 q  I. c
        //}+ B6 {: I: u; @! Q
        //{ make current pivot to `1`
/ n8 d5 Y& c# k        for( int c = _n; c > col; --c){9 a" U1 x# u& F* C- M/ r/ [4 z1 B
            Aug[ rank][ c] /= Aug[ rank][ col];% j' l9 o$ S: u' c1 }$ J& o3 Q
        }
* N2 {; z% c5 _( t0 |% X: O" t" K( j        Aug[ rank][ col] = 1;
( ~  }( ^! m0 y0 G" r2 f' W        //}- \/ {# o; ~) M3 [( u0 z
        //{ make all rows below current pivot in the same column to `0`- Y+ ~3 F6 F1 d+ l! `
        for( int r = rank + 1; r < _m; ++r){" Y5 o6 r  q  Y% Z) d, I
            if( 0 == Db_cmp( fabs( Aug[ r][ col]), 0, Epsilon)){
: \& b0 K2 ~) ]# V# _9 q/ i                continue;
: m3 R8 i5 w5 l4 J  f" M            }
& S8 J5 T# X4 ^+ O  O. |            for( int c = _n; c > col; --c){
+ U, G- n1 k  i! t/ o                Aug[ r][ c] -= Aug[ r][ col] * Aug[ rank][ c];
1 @- ~- n. c' {& w: B6 c$ v. u            }
/ {/ ^% D) Q7 z            Aug[ r][ col] = 0;- `& y6 |: {2 M% s, T
        }
5 L; r% b3 b* F        ++ rank;$ t5 n2 t2 S0 g* p+ v
    }
8 H* X* @4 y0 n    //--
3 }- V6 I$ s7 z    for( int r = rank; r < _m; ++r){
: v1 h& @( ~" V6 [' ^8 k: H% B" P        if( 0 != Db_cmp( Aug[ r][ _n], 0, Epsilon)){
5 v' W" L$ u5 ^- T/ ^- i- q2 ~            return -1;
4 Y; y. ?' w0 n* L        }
; Q" n9 b! s! _" T    }
( O+ _# P$ D' o% m    if( rank != n){
; B+ C3 P8 b; V3 `& D        return 1;: P, t- u  M; F% l. N9 c' p# q
    }! N" y$ |$ j% ]& D& s2 ]4 N
    //> the upper-left `_n * _n` submatrix of `Aug` is a identity-matrix( A/ t9 @2 [# u! j9 O, f7 Y
    for( int r = rank - 1; r > 0; --r){
, H0 ]  }' F" G" ]9 s1 R1 n        for( int rr = 0; rr < r; ++rr){
' F3 Z- ~6 D9 ~9 I8 ^% \6 X3 }            if( 0 == Db_cmp( Aug[ rr][ r], 0, Epsilon)){1 ^" P7 R. [, d& _* ~$ t7 x* U7 [
                continue;
3 u% M% f- Q5 k7 N5 J" r            }
) c: R! T3 U( |: w* C            Aug[ rr][ _n] -= Aug[ rr][ r] * Aug[ r][ _n];& V# N: A/ A8 _. V% g. n0 C
            Aug[ rr][ r] = 0;
! f# ]/ @+ k4 ?" G( N5 M        }5 q8 a& z5 ^/ E2 {  ~' C3 s/ v7 y
    }
! p; f) l' U2 q$ y" ?$ p# S    return 0;
4 t6 r  @6 F1 A}
/ a6 D& B; s* @9 X//} Gaussian elimination
4 X- r. S+ o7 P% F3 E
3 a8 K& b/ `( h! r. u0 H: G. _* v8 H' j' I
您需要登录后才可以回帖 登录 | 注册

本版积分规则

返回首页|Archiver|手机版|小黑屋|易陆发现技术论坛 ( 蜀ICP备2026014127号-1 )

GMT+8, 2026-6-11 23:13 , Processed in 0.021413 second(s), 22 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表