├── .gitignore ├── README.md ├── lab1 ├── FFT │ ├── CMakeLists.txt │ └── main.cpp ├── Quick Sort │ ├── CMakeLists.txt │ └── main.cpp ├── Radix Sort │ ├── CMakeLists.txt │ └── main.cpp └── lab1.pdf ├── lab2 ├── BRT │ ├── CMakeLists.txt │ ├── brt.cpp │ └── 红黑树.pdf ├── Grades │ ├── CMakeLists.txt │ ├── grades.cpp │ └── 成绩单.pdf ├── LIS │ ├── CMakeLists.txt │ ├── lis.cpp │ └── 最长递增子序列.pdf ├── lab2.pdf └── report.pdf ├── lab3 ├── Find0 │ ├── CMakeLists.txt │ ├── find0.cpp │ └── 找零.pdf ├── Largest │ ├── CMakeLists.txt │ ├── largest.cpp │ └── 最大连续子方阵.pdf ├── PrizeNumber │ ├── CMakeLists.txt │ ├── prize.cpp │ └── 领奖台数.pdf ├── Shortest │ ├── CMakeLists.txt │ ├── shortest.cpp │ └── 最短达标区间.pdf ├── lab3.pdf └── report.pdf ├── lab4 ├── Accessibility │ ├── CMakeLists.txt │ ├── access.cpp │ └── 可达性查询.pdf ├── Distance │ ├── CMakeLists.txt │ ├── floyd.cpp │ ├── johnson.cpp │ └── 顶点距离.pdf ├── Flow │ ├── CMakeLists.txt │ ├── fattest.cpp │ ├── shortest.cpp │ └── 最大流.pdf ├── MST │ ├── CMakeLists.txt │ ├── mst.cpp │ └── 次小生成树.pdf ├── lab4.pdf └── report.pdf └── lab5 ├── Circle ├── CMakeLists.txt ├── circle.cpp └── 最小平均权重环.pdf ├── Match ├── CMakeLists.txt ├── match.cpp └── 最小权最大匹配.pdf ├── Substr ├── CMakeLists.txt ├── substr.cpp └── 重复子串因子.pdf ├── Tail ├── CMakeLists.txt ├── ans.out ├── res.out ├── tail.cpp ├── tail_small.cpp ├── test.in └── 尾数还原.pdf ├── lab5.pdf └── report.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | # Report source 2 | *.md 3 | 4 | # Homework 5 | hw*/ 6 | 7 | # Clion file 8 | .idea/ 9 | cmake-build-debug/ 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # USTC-Algorithm 2 | USTC 算法基础 2022SP(陈雪)实验 3 | -------------------------------------------------------------------------------- /lab1/FFT/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21) 2 | project(FFT) 3 | 4 | set(CMAKE_CXX_STANDARD 17) 5 | 6 | add_executable(FFT main.cpp) 7 | -------------------------------------------------------------------------------- /lab1/FFT/main.cpp: -------------------------------------------------------------------------------- 1 | #pragma GCC optimize(2) 2 | 3 | #include 4 | #include 5 | 6 | #define PI 3.1415926535897932384626 7 | 8 | class Complex 9 | { 10 | public: 11 | double x, y; 12 | 13 | 14 | explicit Complex(double a = 0, double b = 0) : x(a), y(b) {} 15 | 16 | 17 | void make(double a = 0, double b = 0) 18 | { 19 | x = a; 20 | y = b; 21 | } 22 | 23 | 24 | Complex operator+(Complex b) const 25 | { 26 | return Complex(x + b.x, y + b.y); 27 | } 28 | 29 | 30 | Complex operator-(Complex b) const 31 | { 32 | return Complex(x - b.x, y - b.y); 33 | } 34 | 35 | 36 | Complex operator*(Complex b) const 37 | { 38 | return Complex(x * b.x - y * b.y, x * b.y + y * b.x); 39 | } 40 | }; 41 | 42 | 43 | inline int ReadInteger() 44 | { 45 | int x = 0, k = 1; 46 | int c = getchar(); 47 | while (c > '9' || c < '0') 48 | { 49 | if (c == '-') 50 | { 51 | k = -1; 52 | } 53 | c = getchar(); 54 | } 55 | while (c >= '0' && c <= '9') 56 | { 57 | x = (x << 3) + (x << 1) + (c ^ 48); 58 | c = getchar(); 59 | } 60 | return x; 61 | } 62 | 63 | 64 | void FFT(Complex *t, Complex *ans, int length, int type) 65 | { 66 | if (length == 1) 67 | { 68 | *ans = *t; 69 | return; 70 | } 71 | Complex wn(std::cos(2 * PI / length), type * std::sin(2 * PI / length)); 72 | Complex w(1, 0); 73 | auto a0 = new Complex[length / 2]; 74 | auto a1 = new Complex[length / 2]; 75 | auto y0 = new Complex[length / 2]; 76 | auto y1 = new Complex[length / 2]; 77 | for (int i = 0; i < length; i += 2) 78 | { 79 | a0[i >> 1] = t[i]; 80 | a1[i >> 1] = t[i + 1]; 81 | } 82 | length >>= 1; 83 | FFT(a0, y0, length, type); 84 | FFT(a1, y1, length, type); 85 | for (int k = 0; k < length; k++) 86 | { 87 | ans[k] = y0[k] + w * y1[k]; 88 | ans[k + length] = y0[k] - w * y1[k]; 89 | w = w * wn; 90 | } 91 | } 92 | 93 | 94 | int main() 95 | { 96 | int n = ReadInteger() + 1; 97 | 98 | int length = 1; 99 | while (length <= n) 100 | { 101 | length <<= 1; 102 | } 103 | length <<= 1; 104 | 105 | auto a = new Complex[length]; 106 | auto b = new Complex[length]; 107 | auto x = new Complex[length]; 108 | auto y = new Complex[length]; 109 | auto z = new Complex[length]; 110 | 111 | for (int i = 0; i < n; i++) 112 | { 113 | a[i].make(ReadInteger(), 0); 114 | } 115 | for (int i = 0; i < n; i++) 116 | { 117 | b[i].make(ReadInteger(), 0); 118 | } 119 | 120 | FFT(a, x, length, 1); 121 | FFT(b, y, length, 1); 122 | 123 | for (int i = 0; i < length; i++) 124 | { 125 | x[i] = x[i] * y[i]; 126 | } 127 | 128 | FFT(x, z, length, -1); 129 | 130 | int cnt = 2 * n - 1; 131 | 132 | for (int i = 0; i < cnt; i++) 133 | { 134 | printf("%d ", int((z[i].x + 0.5)/ length)); 135 | } 136 | return 0; 137 | } -------------------------------------------------------------------------------- /lab1/Quick Sort/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21) 2 | project(Quick_Sort) 3 | 4 | set(CMAKE_CXX_STANDARD 17) 5 | 6 | add_executable(Quick_Sort main.cpp) 7 | -------------------------------------------------------------------------------- /lab1/Quick Sort/main.cpp: -------------------------------------------------------------------------------- 1 | #pragma GCC optimize(2) 2 | 3 | #include 4 | #include 5 | 6 | class MyClass 7 | { 8 | private: 9 | int x, y, z; 10 | 11 | public: 12 | explicit MyClass(int x = 0, int y = 0, int z = 0) : x(x), y(y), z(z) {}; 13 | 14 | 15 | MyClass(MyClass &p) 16 | { 17 | x = p.x; 18 | y = p.y; 19 | z = p.z; 20 | } 21 | 22 | 23 | void Swap(MyClass &p) 24 | { 25 | std::swap(x, p.x); 26 | std::swap(y, p.y); 27 | std::swap(z, p.z); 28 | } 29 | 30 | 31 | void Make(int a, int b, int c) 32 | { 33 | x = a; 34 | y = b; 35 | z = c; 36 | } 37 | 38 | 39 | void Print() const 40 | { 41 | printf("%d %d %d\n", x, y, z); 42 | } 43 | 44 | 45 | bool operator<(MyClass &b) const 46 | { 47 | return (x < b.x) || (x == b.x && y < b.y) || (x == b.x && y == b.y && z < b.z); 48 | } 49 | }; 50 | 51 | 52 | std::random_device rd; 53 | std::default_random_engine rng {rd()}; 54 | 55 | 56 | inline int ReadInteger() 57 | { 58 | int x = 0, k = 1; 59 | int c = getchar(); 60 | while (c > '9' || c < '0') 61 | { 62 | if (c == '-') 63 | { 64 | k = -1; 65 | } 66 | c = getchar(); 67 | } 68 | while (c >= '0' && c <= '9') 69 | { 70 | x = (x << 3) + (x << 1) + (c ^ 48); 71 | c = getchar(); 72 | } 73 | return x * k; 74 | } 75 | 76 | 77 | MyClass *Partition(MyClass *st, MyClass *ed) 78 | { 79 | auto x = new MyClass(*ed); 80 | auto i = st - 1; 81 | for (auto p = st; p != ed; p++) 82 | { 83 | if (*p < *x) 84 | { 85 | i += 1; 86 | i->Swap(*p); 87 | } 88 | } 89 | i += 1; 90 | i->Swap(*ed); 91 | delete x; 92 | return i; 93 | } 94 | 95 | 96 | MyClass *RandomPartition(MyClass *st, MyClass *ed) 97 | { 98 | long k = ed - st; 99 | std::uniform_int_distribution r(0, k); 100 | auto i = st + r(rng); 101 | i->Swap(*ed); 102 | return Partition(st, ed); 103 | } 104 | 105 | 106 | void QuickSort(MyClass *st, MyClass *ed) 107 | { 108 | if (st < ed) 109 | { 110 | auto p = RandomPartition(st, ed); 111 | QuickSort(st, p - 1); 112 | QuickSort(p + 1, ed); 113 | } 114 | } 115 | 116 | 117 | int main() 118 | { 119 | int n; 120 | int a, b, c; 121 | n = ReadInteger(); 122 | auto t = new MyClass[n]; 123 | for (int i = 0; i < n; i++) 124 | { 125 | a = ReadInteger(); 126 | b = ReadInteger(); 127 | c = ReadInteger(); 128 | t[i].Make(a, b, c); 129 | } 130 | QuickSort(t, t + n - 1); 131 | for (int i = 0; i < n; i++) 132 | { 133 | t[i].Print(); 134 | } 135 | delete[] t; 136 | return 0; 137 | } -------------------------------------------------------------------------------- /lab1/Radix Sort/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21) 2 | project(Radix_Sort) 3 | 4 | set(CMAKE_CXX_STANDARD 17) 5 | 6 | add_executable(Radix_Sort main.cpp) 7 | -------------------------------------------------------------------------------- /lab1/Radix Sort/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | int a[2000000] = {}; 6 | 7 | 8 | inline int ReadIntegerUnsigned() 9 | { 10 | int x = 0; 11 | int c = getchar(); 12 | while (c > '9' || c < '0') 13 | { 14 | c = getchar(); 15 | } 16 | while (c >= '0' && c <= '9') 17 | { 18 | x = (x << 3) + (x << 1) + (c ^ 48); 19 | c = getchar(); 20 | } 21 | return x; 22 | } 23 | 24 | 25 | void CountingSort(int *st, int length, int base, int offset) 26 | { 27 | auto temp = (base >> offset); 28 | auto c = new int[temp + 1]; 29 | auto b = new int[length]; 30 | for (int i = 0; i <= temp; i++) 31 | { 32 | c[i] = 0; 33 | } 34 | for (int i = 0; i < length; i++) 35 | { 36 | c[((st[i]) & base) >> offset] = c[((st[i]) & base) >> offset] + 1; 37 | } 38 | for (int i = 1; i <= temp; i++) 39 | { 40 | c[i] = c[i - 1] + c[i]; 41 | } 42 | for (int i = length - 1; i != -1; i--) 43 | { 44 | b[c[((st[i]) & base) >> offset] - 1] = st[i]; 45 | c[((st[i]) & base) >> offset] -= 1; 46 | } 47 | for (int i = 0; i < length; i++) 48 | { 49 | st[i] = b[i]; 50 | } 51 | delete[] c; 52 | delete[] b; 53 | } 54 | 55 | 56 | void RadixSort(int *st, int length, int base, int bit, int maxn) 57 | { 58 | for (int i = 0; i <= maxn; i += bit, base <<= bit) 59 | { 60 | CountingSort(st, length, base, i); 61 | } 62 | } 63 | 64 | 65 | int main() 66 | { 67 | int n = 0; 68 | double maxn = 0; 69 | n = ReadIntegerUnsigned(); 70 | for (int i = 0; i < n; i++) 71 | { 72 | a[i] = ReadIntegerUnsigned(); 73 | maxn = std::fmax(maxn, a[i]); 74 | } 75 | int r = int(ceil(log2(double(n + 1)))); 76 | maxn = ceil(log2(double(maxn + 1))); 77 | RadixSort(a, n, (1 << r) - 1, r, maxn); 78 | for (int i = 0; i < n; i++) 79 | { 80 | printf("%d ", a[i]); 81 | } 82 | return 0; 83 | } -------------------------------------------------------------------------------- /lab1/lab1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab1/lab1.pdf -------------------------------------------------------------------------------- /lab2/BRT/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21) 2 | project(BRT) 3 | 4 | add_definitions(-DDEBUG) 5 | 6 | set(CMAKE_CXX_STANDARD 14) 7 | 8 | add_executable(BRT 9 | brt.cpp) 10 | -------------------------------------------------------------------------------- /lab2/BRT/brt.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class BlackRedTree 4 | { 5 | private: 6 | enum Color {black, red}; 7 | struct Node 8 | { 9 | int val; 10 | int siz; 11 | Node* left; 12 | Node* right; 13 | Node* parent; 14 | Color color; 15 | }; 16 | Node* nil; 17 | Node* root; 18 | void LeftRotate(Node* p) 19 | { 20 | if (p == nil) return; 21 | Node* r = p -> right; 22 | p -> right = r -> left; 23 | if (r -> left != nil) 24 | { 25 | r -> left -> parent = p; 26 | } 27 | r -> parent = p -> parent; 28 | if (p -> parent == nil) 29 | { 30 | root = r; 31 | } 32 | else if (p == p -> parent -> left) 33 | { 34 | p -> parent -> left = r; 35 | } 36 | else 37 | { 38 | p -> parent -> right = r; 39 | } 40 | r -> left = p; 41 | r -> siz = p -> siz; 42 | p -> parent = r; 43 | p -> siz = p -> left -> siz + p -> right -> siz + 1; 44 | } 45 | void RightRotate(Node* p) 46 | { 47 | if (p == nil) return; 48 | Node* l = p -> left; 49 | p -> left = l -> right; 50 | if (l -> right != nil) 51 | { 52 | l -> right -> parent = p; 53 | } 54 | l -> parent = p -> parent; 55 | if (p -> parent == nil) 56 | { 57 | root = l; 58 | } 59 | else if (p == p -> parent -> left) 60 | { 61 | p -> parent -> left = l; 62 | } 63 | else 64 | { 65 | p -> parent -> right = l; 66 | } 67 | l -> right = p; 68 | l -> siz = p -> siz; 69 | p -> parent = l; 70 | p -> siz = p -> left -> siz + p -> right -> siz + 1; 71 | } 72 | void InsertFixUp(Node* z) 73 | { 74 | Node* y; 75 | while (z -> parent -> color == red) 76 | { 77 | if (z -> parent == z -> parent -> parent -> left) 78 | { 79 | y = z -> parent -> parent -> right; 80 | if (y -> color == red) 81 | { 82 | z -> parent -> color = black; 83 | y -> color = black; 84 | z -> parent -> parent -> color = red; 85 | z = z -> parent -> parent; 86 | } 87 | else 88 | { 89 | if (z == z -> parent -> right) 90 | { 91 | z = z -> parent; 92 | LeftRotate(z); 93 | } 94 | z -> parent -> color = black; 95 | z -> parent -> parent -> color = red; 96 | RightRotate(z -> parent -> parent); 97 | } 98 | } 99 | else 100 | { 101 | y = z -> parent -> parent -> left; 102 | if (y -> color == red) 103 | { 104 | z -> parent -> color = black; 105 | y -> color = black; 106 | z -> parent -> parent -> color = red; 107 | z = z -> parent -> parent; 108 | } 109 | else 110 | { 111 | if (z == z-> parent -> left) { 112 | z = z -> parent; 113 | RightRotate(z); 114 | } 115 | z -> parent -> color = black; 116 | z -> parent -> parent -> color = red; 117 | LeftRotate(z -> parent -> parent); 118 | } 119 | } 120 | } 121 | root -> color = black; 122 | } 123 | void InsertNode(Node* z) 124 | { 125 | Node* y = nil; 126 | Node* x = root; 127 | while (x != nil) 128 | { 129 | y = x; 130 | y -> siz += 1; 131 | if (z -> val < x -> val) 132 | { 133 | x = x -> left; 134 | } 135 | else 136 | { 137 | x = x -> right; 138 | } 139 | } 140 | z -> parent = y; 141 | if (y == nil) 142 | { 143 | root = z; 144 | } 145 | else if (z -> val < y -> val) 146 | { 147 | y -> left = z; 148 | } 149 | else 150 | { 151 | y -> right = z; 152 | } 153 | InsertFixUp(z); 154 | } 155 | Node* Minimum(Node* x) 156 | { 157 | while (x -> left != nil) 158 | { 159 | x = x -> left; 160 | } 161 | return x; 162 | } 163 | void Transplant(Node* u, Node* v) 164 | { 165 | if (u -> parent == nil) 166 | { 167 | root = v; 168 | } 169 | else if (u == u -> parent -> left) 170 | { 171 | u -> parent -> left = v; 172 | } 173 | else 174 | { 175 | u -> parent -> right = v; 176 | } 177 | v -> parent = u -> parent; 178 | } 179 | void DeleteFixUp(Node* x) 180 | { 181 | Node* w; 182 | while (x != root && x -> color == black) 183 | { 184 | if (x == x -> parent -> left) 185 | { 186 | w = x -> parent -> right; 187 | if (w -> color == red) 188 | { 189 | w -> color = black; 190 | x -> parent -> color = red; 191 | LeftRotate(x -> parent); 192 | w = x -> parent -> right; 193 | } 194 | if (w -> left -> color == black && w -> right -> color == black) 195 | { 196 | w -> color = red; 197 | x = x -> parent; 198 | } 199 | else 200 | { 201 | if (w -> right -> color == black) 202 | { 203 | w -> left -> color = black; 204 | w -> color = red; 205 | RightRotate(w); 206 | w = x -> parent -> right; 207 | } 208 | w -> color = x -> parent -> color; 209 | x -> parent -> color = black; 210 | w -> right -> color = black; 211 | LeftRotate(x -> parent); 212 | x = root; 213 | } 214 | } 215 | else 216 | { 217 | w = x -> parent -> left; 218 | if (w -> color == red) 219 | { 220 | w -> color = black; 221 | x -> parent -> color = red; 222 | RightRotate(x -> parent); 223 | w = x -> parent -> left; 224 | } 225 | if (w -> right -> color == black && w -> left -> color == black) 226 | { 227 | w -> color = red; 228 | x = x -> parent; 229 | } 230 | else 231 | { 232 | if (w -> left -> color == black) 233 | { 234 | w -> right -> color = black; 235 | w -> color = red; 236 | LeftRotate(w); 237 | w = x -> parent -> left; 238 | } 239 | w -> color = x -> parent -> color; 240 | x -> parent -> color = black; 241 | w -> left -> color = black; 242 | RightRotate(x -> parent); 243 | x = root; 244 | } 245 | } 246 | } 247 | x -> color = black; 248 | } 249 | void DeleteNode(Node* z) 250 | { 251 | Node* y = z; 252 | Node* x; 253 | Node* f; 254 | Color yc = y -> color; 255 | if (z -> left == nil) 256 | { 257 | f = x = z -> right; 258 | Transplant(z, x); 259 | } 260 | else if (z -> right == nil) 261 | { 262 | f = x = z -> left; 263 | Transplant(z, x); 264 | } 265 | else 266 | { 267 | y = Minimum(z -> right); 268 | yc = y -> color; 269 | f = y -> parent; 270 | x = y -> right; 271 | if (y -> parent == z) 272 | { 273 | x -> parent = y; 274 | } 275 | else 276 | { 277 | Transplant(y, x); 278 | y -> right = z -> right; 279 | y -> right -> parent = y; 280 | } 281 | Transplant(z, y); 282 | y -> left = z -> left; 283 | y -> left -> parent = y; 284 | y -> color = z -> color; 285 | } 286 | nil -> siz = 0; 287 | if (f == nil) 288 | { 289 | f = z -> parent; 290 | } 291 | while (f != nil) 292 | { 293 | f -> siz = f -> left -> siz + f -> right -> siz + 1; 294 | f = f -> parent; 295 | } 296 | if (yc == black) 297 | { 298 | DeleteFixUp(x); 299 | } 300 | } 301 | Node* Find(int val) 302 | { 303 | Node* x = root; 304 | while (x != nil && val != x -> val) 305 | { 306 | if (val < x -> val) 307 | { 308 | x = x -> left; 309 | } 310 | else if (val > x -> val) 311 | { 312 | x = x -> right; 313 | } 314 | } 315 | return x; 316 | } 317 | int Findkth(Node* z, int k) 318 | { 319 | if (z == nil) return -1; 320 | if (k <= z -> right -> siz) 321 | { 322 | return Findkth(z -> right, k); 323 | } 324 | else if (k == z -> right -> siz + 1) 325 | { 326 | return z -> val; 327 | } 328 | else 329 | { 330 | return Findkth(z -> left, k - z -> right -> siz - 1); 331 | } 332 | } 333 | Node* FindPre(int val) 334 | { 335 | Node* x = root; 336 | Node* pre = nil; 337 | while (x != nil) 338 | { 339 | if (x -> val <= val) 340 | { 341 | pre = x; 342 | x = x -> right; 343 | } 344 | else 345 | { 346 | x = x -> left; 347 | } 348 | } 349 | return pre; 350 | } 351 | Node* FindNext(int val) 352 | { 353 | Node* x = root; 354 | Node* nxt = nil; 355 | while (x != nil) 356 | { 357 | if (x -> val >= val) 358 | { 359 | nxt = x; 360 | x = x -> left; 361 | } 362 | else 363 | { 364 | x = x -> right; 365 | } 366 | } 367 | return nxt; 368 | } 369 | int GetRank(Node* z, int val) 370 | { 371 | if (z == nil) return 0; 372 | if (val == z -> val) 373 | { 374 | return z -> left -> siz + 1; 375 | } 376 | else if (val < z -> val) 377 | { 378 | return GetRank(z -> left, val); 379 | } 380 | else 381 | { 382 | return z -> left -> siz + 1 + GetRank(z -> right, val); 383 | } 384 | } 385 | public: 386 | BlackRedTree() 387 | { 388 | nil = new Node{0, 0, nullptr, nullptr, nullptr, black}; 389 | nil -> left = nil -> right = nil -> parent = nil; 390 | root = nil; 391 | } 392 | void Insert(int val) 393 | { 394 | Node* z = new Node{val, 1, nil, nil, nil, red}; 395 | InsertNode(z); 396 | DebugPrintTree(); 397 | } 398 | void Delete(int val) 399 | { 400 | Node* x = Find(val); 401 | DeleteNode(x); 402 | DebugPrintTree(); 403 | } 404 | int Findkth(int k) 405 | { 406 | DebugPrintTree(); 407 | return Findkth(root, k); 408 | } 409 | int UpperBound(int val) 410 | { 411 | DebugPrintTree(); 412 | return FindNext(val) -> val; 413 | } 414 | int Count(int l, int r) 415 | { 416 | Node* pre = FindPre(r); 417 | Node* nxt = FindNext(l); 418 | DebugPrintTree(); 419 | if (pre == nil || nxt == nil) 420 | { 421 | return 0; 422 | } 423 | return GetRank(root, pre -> val) - GetRank(root, nxt -> val) + 1; 424 | } 425 | #ifdef DEBUG 426 | static void DebugPrintMessage(Node* p) 427 | { 428 | std::cout << "val: " << p -> val << " siz: " << p -> siz << " color: " << (p -> color ? "R" : "B") << std::endl; 429 | } 430 | void DebugPrintNode(Node* p, int step, int valid, bool right) 431 | { 432 | if (p == nil) return; 433 | for (int i = 0; i < step; i++) 434 | { 435 | std::cout << ((valid & (1 << (i - 1))) == 0 ? " ": "│ "); 436 | } 437 | std::cout << (right ? "└ " : "├ "); 438 | DebugPrintMessage(p); 439 | DebugPrintNode(p -> left, step + 1, valid | (1 << step), p -> right == nil); 440 | DebugPrintNode(p -> right, step + 1, valid & ~(1 << step), true); 441 | } 442 | #endif 443 | void DebugPrintTree() 444 | { 445 | #ifdef DEBUG 446 | std::cout << "/******************/" << std::endl << "TREE" << std::endl; 447 | DebugPrintNode(root, 0, 0, true); 448 | std::cout << "/******************/" << std::endl; 449 | #endif 450 | } 451 | }; 452 | 453 | class Solution 454 | { 455 | private: 456 | BlackRedTree brt; 457 | public: 458 | void HandleInstruction() 459 | { 460 | char op = ' '; 461 | int x, y; 462 | while (op == ' ' || op == '\n' || op == '\r') 463 | { 464 | std::cin >> op; 465 | } 466 | switch (op) 467 | { 468 | case 'I': 469 | std::cin >> x; 470 | brt.Insert(x); 471 | break; 472 | case 'D': 473 | std::cin >> x; 474 | brt.Delete(x); 475 | break; 476 | case 'S': 477 | std::cin >> x; 478 | std::cout << brt.Findkth(x) << std::endl; 479 | break; 480 | case 'L': 481 | std::cin >> x; 482 | std::cout << brt.UpperBound(x) << std::endl; 483 | break; 484 | case 'T': 485 | std::cin >> x >> y; 486 | std::cout << brt.Count(x, y) << std::endl; 487 | break; 488 | default: 489 | break; 490 | } 491 | } 492 | }; 493 | 494 | int main() 495 | { 496 | int n; 497 | std::cin >> n; 498 | Solution solution; 499 | for (int i = 0; i < n; i++) 500 | { 501 | solution.HandleInstruction(); 502 | } 503 | return 0; 504 | } -------------------------------------------------------------------------------- /lab2/BRT/红黑树.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab2/BRT/红黑树.pdf -------------------------------------------------------------------------------- /lab2/Grades/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21) 2 | project(Grades) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | add_executable(Grades 7 | grades.cpp) 8 | -------------------------------------------------------------------------------- /lab2/Grades/grades.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define TABLE_MAX 15000000 6 | #define HEAP_MAX 700050 7 | #define NAME_MAX 1000 8 | 9 | class Solution 10 | { 11 | private: 12 | int siz = 0, cnt = 0; 13 | int table[TABLE_MAX] = {}; 14 | std::string bullet[NAME_MAX] = {}; 15 | struct Student 16 | { 17 | std::string name; 18 | int score{}; 19 | }; 20 | Student heap[HEAP_MAX]; 21 | friend bool operator<(const Student& a, const Student& b) 22 | { 23 | return a.score < b.score; 24 | } 25 | private: 26 | 27 | static int HashName(const std::string& name) 28 | { 29 | int ans = 0; 30 | for (auto p : name) 31 | { 32 | ans = ans * 28 - 64 + p; 33 | } 34 | return ans; 35 | } 36 | 37 | int& GetIndex(const std::string& name) 38 | { 39 | return table[HashName(name)]; 40 | } 41 | 42 | void MaxHeapify(int index) 43 | { 44 | int l = index << 1; 45 | int r = l + 1; 46 | int largest = index; 47 | if (l <= siz && !(heap[l] < heap[index])) 48 | { 49 | largest = l; 50 | } 51 | if (r <= siz && !(heap[r] < heap[largest])) 52 | { 53 | largest = r; 54 | } 55 | if (largest != index) 56 | { 57 | std::swap(heap[index], heap[largest]); 58 | GetIndex(heap[index].name) = index; 59 | GetIndex(heap[largest].name) = largest; 60 | MaxHeapify(largest); 61 | } 62 | } 63 | 64 | void DeleteStudent(const std::string& name) 65 | { 66 | if (GetIndex(name) > siz || GetIndex(name) == 0) return; 67 | heap[GetIndex(name)].score = __INT_MAX__; 68 | for (int i = GetIndex(name); i > 1; i = i >> 1) 69 | { 70 | std::swap(heap[i], heap[i >> 1]); 71 | GetIndex(heap[i].name) = i; 72 | GetIndex(heap[i >> 1].name) = i >> 1; 73 | } 74 | std::swap(heap[1], heap[siz]); 75 | GetIndex(heap[1].name) = 1; 76 | GetIndex(heap[siz].name) = 0; 77 | siz -= 1; 78 | MaxHeapify(1); 79 | } 80 | 81 | void InsertStudent(const std::string& name, int score) 82 | { 83 | siz += 1; 84 | heap[siz] = Student{name, score}; 85 | GetIndex(name) = siz; 86 | for (int i = siz; i > 1 && heap[i >> 1] < heap[i]; i = i >> 1) 87 | { 88 | std::swap(heap[i], heap[i >> 1]); 89 | GetIndex(heap[i].name) = i; 90 | GetIndex(heap[i >> 1].name) = i >> 1; 91 | } 92 | } 93 | 94 | void PrintScore(const std::string& name) 95 | { 96 | std::cout << heap[GetIndex(name)].score << std::endl; 97 | } 98 | 99 | void PrintBest(int index) 100 | { 101 | if (index > siz) return; 102 | if (heap[index].score == heap[1].score) 103 | { 104 | bullet[cnt++] = heap[index].name; 105 | PrintBest(index << 1); 106 | PrintBest((index << 1) + 1); 107 | } 108 | } 109 | 110 | 111 | public: 112 | void HandleInstruction() 113 | { 114 | char op = ' '; 115 | std::string name; 116 | int score; 117 | while (op == ' ' || op == '\n' || op == '\r') std::cin >> op; 118 | switch (op) 119 | { 120 | case 'I': 121 | std::cin >> name >> score; 122 | InsertStudent(name, score); 123 | break; 124 | case 'D': 125 | std::cin >> name; 126 | DeleteStudent(name); 127 | break; 128 | case 'S': 129 | std::cin >> name; 130 | PrintScore(name); 131 | break; 132 | case 'F': 133 | cnt = 0; 134 | PrintBest(1); 135 | std::sort(bullet, bullet + cnt); 136 | for (int i = 0; i < cnt; i++) 137 | { 138 | std::cout << bullet[i] << std::endl; 139 | } 140 | break; 141 | default: 142 | break; 143 | } 144 | } 145 | 146 | void Initiate() 147 | { 148 | std::memset(table, 0, sizeof table); 149 | } 150 | }; 151 | 152 | Solution solution; 153 | 154 | int main() 155 | { 156 | int n; 157 | std::cin >> n; 158 | solution.Initiate(); 159 | for (int i = 0; i < n; i++) 160 | { 161 | solution.HandleInstruction(); 162 | } 163 | return 0; 164 | } -------------------------------------------------------------------------------- /lab2/Grades/成绩单.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab2/Grades/成绩单.pdf -------------------------------------------------------------------------------- /lab2/LIS/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21) 2 | project(LIS) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | add_executable(LIS 7 | lis.cpp) 8 | -------------------------------------------------------------------------------- /lab2/LIS/lis.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAX_N 1200000 4 | 5 | class Solution 6 | { 7 | private: 8 | int n = 0; 9 | int a[MAX_N] = {}; 10 | int dp[MAX_N] = {}; 11 | 12 | private: 13 | void Initiate() 14 | { 15 | for (auto& p : dp) p = __INT_MAX__; 16 | } 17 | 18 | static int LowerBound(const int* st, int num, int k) 19 | { 20 | int l = 0, r = num, mid; 21 | while (l < r) 22 | { 23 | mid = (l + r) >> 1; 24 | if (st[mid] < k) l = mid + 1; 25 | else r = mid; 26 | } 27 | return l; 28 | } 29 | 30 | public: 31 | int LongestIncreaseSubsequence() 32 | { 33 | Initiate(); 34 | for (int i = 0; i < n; i++) 35 | { 36 | auto lb = LowerBound(dp, n, a[i]); 37 | dp[lb] = a[i]; 38 | } 39 | return LowerBound(dp, n, __INT_MAX__); 40 | } 41 | 42 | void Input() 43 | { 44 | std::cin >> n; 45 | for (int i = 0; i < n; i++) 46 | { 47 | std::cin >> a[i]; 48 | } 49 | } 50 | }; 51 | 52 | int main() 53 | { 54 | Solution solution; 55 | 56 | solution.Input(); 57 | std::cout << solution.LongestIncreaseSubsequence(); 58 | 59 | return 0; 60 | } -------------------------------------------------------------------------------- /lab2/LIS/最长递增子序列.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab2/LIS/最长递增子序列.pdf -------------------------------------------------------------------------------- /lab2/lab2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab2/lab2.pdf -------------------------------------------------------------------------------- /lab2/report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab2/report.pdf -------------------------------------------------------------------------------- /lab3/Find0/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21) 2 | project(Find0) 3 | 4 | add_definitions(-DDEBUG) 5 | 6 | set(CMAKE_CXX_STANDARD 17) 7 | 8 | add_executable(Find0 9 | find0.cpp) 10 | -------------------------------------------------------------------------------- /lab3/Find0/find0.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MOD 1000000007 5 | #define MAXV 50000 6 | 7 | class Solution 8 | { 9 | private: 10 | int ans[MAXV]{}; 11 | public: 12 | int n, v; 13 | int* coins; 14 | public: 15 | Solution(int nn, int vv) 16 | { 17 | n = nn; 18 | v = vv; 19 | coins = new int[nn]; 20 | std::memset(ans, 0, sizeof ans); 21 | } 22 | ~Solution() 23 | { 24 | delete[] coins; 25 | } 26 | void ReadCoins() 27 | { 28 | for (int i = 0; i < n ; i++) 29 | { 30 | std::cin >> coins[i]; 31 | } 32 | } 33 | int Solve() 34 | { 35 | ans[0] = 1; 36 | for (int i = 0; i < n; i++) 37 | { 38 | for (int j = 1; j <= v; j++) 39 | { 40 | if (j >= coins[i]) 41 | { 42 | ans[j] = (ans[j] + ans[j - coins[i]]) % MOD; 43 | } 44 | } 45 | } 46 | return ans[v]; 47 | } 48 | }; 49 | 50 | int main() 51 | { 52 | int n, v; 53 | std::cin >> n >> v; 54 | Solution solution = Solution(n, v); 55 | solution.ReadCoins(); 56 | std::cout << solution.Solve() << std::endl; 57 | return 0; 58 | } -------------------------------------------------------------------------------- /lab3/Find0/找零.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab3/Find0/找零.pdf -------------------------------------------------------------------------------- /lab3/Largest/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21) 2 | project(Largest) 3 | 4 | add_definitions(-DDEBUG) 5 | 6 | set(CMAKE_CXX_STANDARD 14) 7 | 8 | add_executable(Largest 9 | largest.cpp) 10 | -------------------------------------------------------------------------------- /lab3/Largest/largest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXN 2001 4 | 5 | class Solution 6 | { 7 | private: 8 | int n; 9 | int a[MAXN][MAXN]{}; 10 | int line[MAXN][MAXN]{}; 11 | int row[MAXN][MAXN]{}; 12 | int ans[MAXN][MAXN]{}; 13 | private: 14 | static int Min3(int a, int b, int c) 15 | { 16 | a = a < b ? a : b; 17 | return a < c ? a : c; 18 | } 19 | public: 20 | explicit Solution(int nn) 21 | { 22 | n = nn; 23 | } 24 | void ReadMatrix(std::istream& in) 25 | { 26 | for (int i = 1; i <= n; i++) 27 | { 28 | for (int j = 1; j <= n; j++) 29 | { 30 | in >> a[i][j]; 31 | } 32 | } 33 | } 34 | int Solve() 35 | { 36 | int res = 0; 37 | for (int i = 1; i <= n; i++) 38 | { 39 | for (int j = 1; j <= n; j++) 40 | { 41 | if (a[i][j] == 1) 42 | { 43 | line[i][j] = line[i - 1][j] + 1; 44 | row[i][j] = row[i][j - 1] + 1; 45 | ans[i][j] = Min3(line[i][j], row[i][j], ans[i - 1][j - 1] + 1); 46 | if (ans[i][j] > res) 47 | { 48 | res = ans[i][j]; 49 | } 50 | } 51 | else 52 | { 53 | line[i][j] = 0; 54 | row[i][j] = 0; 55 | ans[i][j] = 0; 56 | } 57 | } 58 | } 59 | return res; 60 | } 61 | }; 62 | 63 | int main() 64 | { 65 | int n; 66 | std::cin >> n; 67 | Solution solution = Solution(n); 68 | solution.ReadMatrix(std::cin); 69 | std::cout << solution.Solve(); 70 | return 0; 71 | } -------------------------------------------------------------------------------- /lab3/Largest/最大连续子方阵.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab3/Largest/最大连续子方阵.pdf -------------------------------------------------------------------------------- /lab3/PrizeNumber/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21) 2 | project(PrizeNumber) 3 | 4 | add_definitions(-DDEBUG) 5 | 6 | set(CMAKE_CXX_STANDARD 14) 7 | 8 | add_executable(PrizeNumber 9 | prize.cpp) 10 | -------------------------------------------------------------------------------- /lab3/PrizeNumber/prize.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class Solution 4 | { 5 | private: 6 | int n; 7 | long long* a; 8 | long long* temp; 9 | long long* tempOrder; 10 | long long* tempReverse; 11 | long long* orderHead; 12 | long long* reverseDf; 13 | private: 14 | #ifdef DEBUG 15 | static void Print(long long* array, int l, int r) 16 | { 17 | int mid = (l + r) >> 1; 18 | while (l <= r) 19 | { 20 | if (l == mid + 1) 21 | { 22 | std::cout << "|\t"; 23 | } 24 | std::cout << array[l] << "\t"; 25 | l += 1; 26 | } 27 | std::cout << std::endl; 28 | } 29 | #endif 30 | long long MergeSort(int l, int r) 31 | { 32 | if (l == r) return 0; 33 | int mid = (l + r) >> 1; 34 | long long sum = MergeSort(l, mid) + MergeSort(mid + 1, r); 35 | long long cnt = 0; 36 | int i, j, p; 37 | #ifdef DEBUG 38 | std::cout << "/******************/" << std::endl; 39 | Print(a, l, r); 40 | Print(orderHead, l, r); 41 | Print(reverseDf, l, r); 42 | #endif 43 | for (p = l, i = l, j = mid + 1; i <= mid && j <= r; p += 1) 44 | { 45 | if (a[i] <= a[j]) 46 | { 47 | temp[p] = a[i]; 48 | tempOrder[p] = orderHead[i] + r - j + 1; 49 | tempReverse[p] = reverseDf[i] + j - 1 - mid; 50 | cnt += orderHead[i] * (j - mid - 1); 51 | i += 1; 52 | } 53 | else 54 | { 55 | temp[p] = a[j]; 56 | tempOrder[p] = orderHead[j]; 57 | tempReverse[p] = reverseDf[j] + i - 1 - mid; 58 | cnt += reverseDf[j] * (i - l); 59 | j += 1; 60 | } 61 | } 62 | while (i <= mid) 63 | { 64 | temp[p] = a[i]; 65 | tempOrder[p] = orderHead[i]; 66 | tempReverse[p] = reverseDf[i] + r - mid; 67 | cnt += orderHead[i] * (r - mid); 68 | i += 1; 69 | p += 1; 70 | } 71 | while (j <= r) 72 | { 73 | temp[p] = a[j]; 74 | tempOrder[p] = orderHead[j]; 75 | tempReverse[p] = reverseDf[j]; 76 | cnt += reverseDf[j] * (mid + 1 - l); 77 | j += 1; 78 | p += 1; 79 | } 80 | while (l <= r) 81 | { 82 | a[l] = temp[l]; 83 | orderHead[l] = tempOrder[l]; 84 | reverseDf[l] = tempReverse[l]; 85 | l += 1; 86 | } 87 | #ifdef DEBUG 88 | std::cout << "sum += " << cnt << std::endl; 89 | std::cout << "/******************/" << std::endl; 90 | #endif 91 | return sum + cnt; 92 | } 93 | public: 94 | explicit Solution(int nn) 95 | { 96 | n = nn; 97 | a = new long long[n]; 98 | temp = new long long[n]; 99 | tempOrder = new long long[n]; 100 | tempReverse = new long long[n]; 101 | orderHead = new long long[n]; 102 | reverseDf = new long long[n]; 103 | } 104 | ~Solution() 105 | { 106 | delete[] temp; 107 | delete[] tempOrder; 108 | delete[] tempReverse; 109 | delete[] orderHead; 110 | delete[] reverseDf; 111 | } 112 | void ReadLine(std::istream& in) 113 | { 114 | for (int i = 0; i < n; i++) 115 | { 116 | in >> a[i]; 117 | tempOrder[i] = tempReverse[i] = orderHead[i] = reverseDf[i] = 0; 118 | } 119 | } 120 | long long Solve() 121 | { 122 | return MergeSort(0, n - 1); 123 | } 124 | }; 125 | 126 | int main() 127 | { 128 | int n; 129 | std::cin >> n; 130 | Solution solution = Solution(n); 131 | solution.ReadLine(std::cin); 132 | std::cout << solution.Solve(); 133 | return 0; 134 | } -------------------------------------------------------------------------------- /lab3/PrizeNumber/领奖台数.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab3/PrizeNumber/领奖台数.pdf -------------------------------------------------------------------------------- /lab3/Shortest/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21) 2 | project(Shortest) 3 | 4 | add_definitions(-DDEBUG) 5 | 6 | set(CMAKE_CXX_STANDARD 14) 7 | 8 | add_executable(Shortest 9 | shortest.cpp) 10 | -------------------------------------------------------------------------------- /lab3/Shortest/shortest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | class Solution 6 | { 7 | private: 8 | int n; 9 | int k; 10 | long long* a; 11 | std::vector > vec; 12 | private: 13 | static int Min2(int a, int b) 14 | { 15 | return a < b ? a : b; 16 | } 17 | public: 18 | Solution(int nn, int kk) 19 | { 20 | n = nn; 21 | k = kk; 22 | a = new long long[n]; 23 | vec.resize(n); 24 | vec.clear(); 25 | } 26 | ~Solution() 27 | { 28 | delete[] a; 29 | } 30 | void ReadLine(std::istream& in) 31 | { 32 | in >> a[0]; 33 | for (int i = 1; i < n; i++) 34 | { 35 | in >> a[i]; 36 | a[i] += a[i - 1]; 37 | } 38 | } 39 | int Solve() 40 | { 41 | int ans = __INT_MAX__; 42 | for (int i = 0; i < n; i++) 43 | { 44 | if (a[i] <= vec.back().first) 45 | { 46 | auto it = std::lower_bound(vec.begin(), vec.end(), std::make_pair(a[i], 0)); 47 | vec.erase(it, vec.end()); 48 | } 49 | vec.emplace_back(a[i], i); 50 | auto it = std::upper_bound(vec.begin(), vec.end(), std::make_pair(a[i] - k, 0)) - 1; 51 | if (it >= vec.begin()) 52 | { 53 | ans = Min2(ans, i - it -> second); 54 | } 55 | #ifdef DEBUG 56 | std::cout << "/******************/" << std::endl; 57 | for (auto p : vec) 58 | { 59 | std::cout << p.first << " "; 60 | } 61 | std::cout << std::endl; 62 | std::cout << "it = " << it - vec.begin() << std::endl; 63 | std::cout << "ans = " << ans << std::endl; 64 | std::cout << "/******************/" << std::endl; 65 | #endif 66 | } 67 | return ans; 68 | } 69 | }; 70 | 71 | int main() 72 | { 73 | int n, k; 74 | std::cin >> n >> k; 75 | Solution solution(n, k); 76 | solution.ReadLine(std::cin); 77 | std::cout << solution.Solve(); 78 | return 0; 79 | } -------------------------------------------------------------------------------- /lab3/Shortest/最短达标区间.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab3/Shortest/最短达标区间.pdf -------------------------------------------------------------------------------- /lab3/lab3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab3/lab3.pdf -------------------------------------------------------------------------------- /lab3/report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab3/report.pdf -------------------------------------------------------------------------------- /lab4/Accessibility/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21) 2 | project(Accessibility) 3 | 4 | add_definitions(-DDEBUG) 5 | 6 | set(CMAKE_CXX_STANDARD 14) 7 | 8 | add_executable(Accessibility 9 | access.cpp) 10 | -------------------------------------------------------------------------------- /lab4/Accessibility/access.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define SCC_MAX 1001 5 | 6 | class Graph 7 | { 8 | private: 9 | int v; 10 | int e; 11 | std::vector* edge; 12 | int cnt; 13 | int sc; 14 | int top; 15 | int* scc; 16 | int* dfn; 17 | int* low; 18 | int* stack; 19 | bool* ins; 20 | bool* vis; 21 | bool** acs; 22 | private: 23 | void Tarjan(int u) 24 | { 25 | dfn[u] = low[u] = ++cnt; 26 | ins[u] = true; 27 | stack[++top] = u; 28 | for (int& p : edge[u]) 29 | { 30 | if (dfn[p] == 0) 31 | { 32 | Tarjan(p); 33 | low[u] = std::min(low[u], low[p]); 34 | } 35 | else if (ins[p]) 36 | { 37 | low[u] = std::min(low[u], dfn[p]); 38 | } 39 | } 40 | if (dfn[u] == low[u]) 41 | { 42 | sc++; 43 | do 44 | { 45 | scc[stack[top]] = sc; 46 | ins[stack[top]] = false; 47 | }while (stack[top--] != u); 48 | } 49 | } 50 | void DFS(int u) 51 | { 52 | acs[scc[u]][scc[u]] = true; 53 | for (auto& p : edge[u]) 54 | { 55 | if (!vis[p]) 56 | { 57 | vis[p] = true; 58 | acs[scc[u]][scc[p]] = true; 59 | DFS(p); 60 | } 61 | for (int i = 1; i <= sc; i++) 62 | { 63 | if (acs[scc[p]][i]) 64 | { 65 | acs[scc[u]][i] = true; 66 | } 67 | } 68 | } 69 | } 70 | public: 71 | Graph(int vv, int ee) 72 | { 73 | v = vv + 1; 74 | e = ee; 75 | edge = new std::vector[v]; 76 | cnt = 0; 77 | sc = 0; 78 | top = 0; 79 | scc = new int[v]; 80 | dfn = new int[v]; 81 | low = new int[v]; 82 | stack = new int[v]; 83 | ins = new bool[v]; 84 | vis = new bool[v]; 85 | acs = new bool*[SCC_MAX]; 86 | for (int i = 0; i < SCC_MAX; i++) 87 | { 88 | acs[i] = new bool[v]; 89 | } 90 | } 91 | ~Graph() 92 | { 93 | delete[] edge; 94 | delete[] scc; 95 | delete[] dfn; 96 | delete[] low; 97 | delete[] ins; 98 | } 99 | void AddEdge(int from, int to) 100 | { 101 | edge[from].push_back(to); 102 | } 103 | bool IsArrival(int from, int to) const 104 | { 105 | return acs[scc[from]][scc[to]]; 106 | } 107 | void Initiate() 108 | { 109 | for (int i = 1; i < v; i++) 110 | { 111 | if (dfn[i] == 0) 112 | { 113 | Tarjan(i); 114 | } 115 | } 116 | for (int i = 1; i < v; i++) 117 | { 118 | if (!vis[i]) 119 | { 120 | vis[i] = true; 121 | DFS(i); 122 | } 123 | } 124 | #ifdef DEBUG 125 | std::cout << "/******************/" <> n >> m; 145 | Graph graph(n, m); 146 | for (int i = 0; i < m; i++) 147 | { 148 | std::cin >> u >> v; 149 | graph.AddEdge(u, v); 150 | } 151 | graph.Initiate(); 152 | std::cin >> q; 153 | for (int i = 0; i < q; i++) 154 | { 155 | std::cin >> u >> v; 156 | std::cout << (int)graph.IsArrival(u, v) << std::endl; 157 | } 158 | return 0; 159 | } -------------------------------------------------------------------------------- /lab4/Accessibility/可达性查询.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab4/Accessibility/可达性查询.pdf -------------------------------------------------------------------------------- /lab4/Distance/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21) 2 | project(Floyd) 3 | project(Johnson) 4 | 5 | add_definitions(-DDEBUG) 6 | 7 | set(CMAKE_CXX_STANDARD 14) 8 | 9 | add_executable(Floyd 10 | floyd.cpp) 11 | 12 | add_executable(Johnson 13 | johnson.cpp) 14 | -------------------------------------------------------------------------------- /lab4/Distance/floyd.cpp: -------------------------------------------------------------------------------- 1 | // Floyd version 2 | #include 3 | #include 4 | 5 | class Graph 6 | { 7 | private: 8 | int v; 9 | bool negative; 10 | int** dis; 11 | public: 12 | static constexpr int infDis = 0x0fffffff; 13 | public: 14 | explicit Graph(int vv) 15 | { 16 | v = vv + 1; 17 | negative = false; 18 | dis = new int*[v]; 19 | for (int i = 0; i < v; i++) 20 | { 21 | dis[i] = new int[v]; 22 | for (int j = 0; j < v; j++) 23 | { 24 | dis[i][j] = infDis; 25 | } 26 | } 27 | } 28 | ~Graph() 29 | { 30 | for (int i = 0; i < v; i++) 31 | { 32 | delete[] dis[i]; 33 | } 34 | delete[] dis; 35 | } 36 | void AddEdge(int from, int to, int val) 37 | { 38 | dis[from][to] = val; 39 | } 40 | void SolveDistance() 41 | { 42 | for (int k = 1; k < v; k++) 43 | { 44 | for (int i = 1; i < v; i++) 45 | { 46 | for (int j = 1; j < v; j++) 47 | { 48 | dis[i][j] = std::min(dis[i][j], dis[i][k] + dis[k][j]); 49 | } 50 | } 51 | for (int i = 1; i < v; i++) 52 | { 53 | for (int j = 1; j < v; j++) 54 | { 55 | if (dis[i][j] > dis[i][k] + dis[k][j]) 56 | { 57 | negative = true; 58 | return; 59 | } 60 | } 61 | } 62 | } 63 | } 64 | int Distance(int from, int to) 65 | { 66 | return dis[from][to]; 67 | } 68 | bool IsNegative() const 69 | { 70 | return negative; 71 | } 72 | }; 73 | 74 | int main() 75 | { 76 | int n, m, u, v, w, q; 77 | std::cin >> n >> m; 78 | Graph graph(n); 79 | for (int i = 0; i < m; i++) 80 | { 81 | std::cin >> u >> v >> w; 82 | graph.AddEdge(u, v, w); 83 | } 84 | graph.SolveDistance(); 85 | if (graph.IsNegative()) 86 | { 87 | std::cout << "negative-weight cycle" << std::endl; 88 | return 0; 89 | } 90 | std::cin >> q; 91 | for (int i = 0; i < q; i++) 92 | { 93 | std::cin >> u >> v; 94 | std::cout << graph.Distance(u, v) << std::endl; 95 | } 96 | return 0; 97 | } -------------------------------------------------------------------------------- /lab4/Distance/johnson.cpp: -------------------------------------------------------------------------------- 1 | // Johnson version 2 | #include 3 | #include 4 | #include 5 | 6 | class Graph 7 | { 8 | private: 9 | class Edge 10 | { 11 | public: 12 | int to; 13 | int val; 14 | public: 15 | explicit Edge(int _to, int _val = infDis) 16 | { 17 | to = _to; 18 | val = _val; 19 | } 20 | ~Edge() = default; 21 | }; 22 | int v; 23 | bool negative; 24 | int** dis; 25 | std::vector* edge; 26 | public: 27 | static constexpr int infDis = 0x0fffffff; 28 | private: 29 | void BellmanFord() 30 | { 31 | dis[0][0] = 0; 32 | for (int i = 1; i < v; i++) 33 | { 34 | for (int j = 0; j < v; j++) 35 | { 36 | for (auto& e : edge[j]) 37 | { 38 | dis[0][e.to] = std::min(dis[0][e.to], dis[0][j] + e.val); 39 | } 40 | } 41 | } 42 | for (int j = 0; j < v; j++) 43 | { 44 | for (auto& e : edge[j]) 45 | { 46 | if (dis[0][e.to] > dis[0][j] + e.val) 47 | { 48 | negative = true; 49 | return; 50 | } 51 | } 52 | } 53 | } 54 | void Dijkstra(int u) 55 | { 56 | dis[u][u] = 0; 57 | std::priority_queue, std::vector>, std::greater<>> q; 58 | q.push(std::make_pair(0, u)); 59 | while (!q.empty()) 60 | { 61 | int p = q.top().second; 62 | q.pop(); 63 | for (auto& e : edge[p]) 64 | { 65 | if(dis[u][e.to] > dis[u][p] + e.val) 66 | { 67 | dis[u][e.to] = dis[u][p] + e.val; 68 | q.emplace(dis[u][e.to], e.to); 69 | } 70 | } 71 | } 72 | } 73 | public: 74 | explicit Graph(int vv) 75 | { 76 | v = vv + 1; 77 | negative = false; 78 | dis = new int*[v]; 79 | for (int i = 0; i < v; i++) 80 | { 81 | dis[i] = new int[v]; 82 | for (int j = 0; j < v; j++) 83 | { 84 | dis[i][j] = infDis; 85 | } 86 | } 87 | edge = new std::vector[v]; 88 | } 89 | ~Graph() 90 | { 91 | for (int i = 0; i < v; i++) 92 | { 93 | delete[] dis[i]; 94 | } 95 | delete[] dis; 96 | delete[] edge; 97 | } 98 | void AddEdge(int from, int to, int val) 99 | { 100 | edge[from].emplace_back(to, val); 101 | } 102 | void SolveDistance() 103 | { 104 | for (int i = 1; i < v; i++) 105 | { 106 | AddEdge(0, i, 0); 107 | } 108 | BellmanFord(); 109 | if (negative) 110 | { 111 | return; 112 | } 113 | for (int i = 0; i < v; i++) 114 | { 115 | for (auto& e : edge[i]) 116 | { 117 | e.val = e.val + dis[0][i] - dis[0][e.to]; 118 | } 119 | } 120 | for (int i = 1; i < v; i++) 121 | { 122 | Dijkstra(i); 123 | for (int j = 1; j < v; j++) 124 | { 125 | dis[i][j] = dis[i][j] + dis[0][j] - dis[0][i]; 126 | } 127 | } 128 | } 129 | int Distance(int from, int to) 130 | { 131 | return dis[from][to]; 132 | } 133 | bool IsNegative() const 134 | { 135 | return negative; 136 | } 137 | }; 138 | 139 | int main() 140 | { 141 | int n, m, u, v, w, q; 142 | std::cin >> n >> m; 143 | Graph graph(n); 144 | for (int i = 0; i < m; i++) 145 | { 146 | std::cin >> u >> v >> w; 147 | graph.AddEdge(u, v, w); 148 | } 149 | graph.SolveDistance(); 150 | if (graph.IsNegative()) 151 | { 152 | std::cout << "negative-weight cycle" << std::endl; 153 | return 0; 154 | } 155 | std::cin >> q; 156 | for (int i = 0; i < q; i++) 157 | { 158 | std::cin >> u >> v; 159 | std::cout << graph.Distance(u, v) << std::endl; 160 | } 161 | return 0; 162 | } -------------------------------------------------------------------------------- /lab4/Distance/顶点距离.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab4/Distance/顶点距离.pdf -------------------------------------------------------------------------------- /lab4/Flow/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21) 2 | project(Shortest) 3 | project(Fattest) 4 | 5 | add_definitions(-DDEBUG) 6 | 7 | set(CMAKE_CXX_STANDARD 17) 8 | 9 | add_executable(Shortest 10 | shortest.cpp) 11 | 12 | add_executable(Fattest 13 | fattest.cpp) -------------------------------------------------------------------------------- /lab4/Flow/fattest.cpp: -------------------------------------------------------------------------------- 1 | // Fattest version 2 | #include 3 | #include 4 | 5 | class Graph 6 | { 7 | private: 8 | int v; 9 | int* pre; 10 | int** cf; 11 | private: 12 | bool BFS(int from, int to) 13 | { 14 | for (int i = 0; i < v; i++) 15 | { 16 | pre[i] = -1; 17 | } 18 | pre[from] = from; 19 | // Use Heap to get fattest node(edge) 20 | std::priority_queue> q; 21 | q.push(std::make_pair(0, from)); 22 | while (!q.empty()) 23 | { 24 | int u = q.top().second; 25 | q.pop(); 26 | for (int i = 1; i < v; i++) 27 | { 28 | if (cf[u][i] > 0 && pre[i] == -1) 29 | { 30 | pre[i] = u; 31 | q.push(std::make_pair(cf[u][i], i)); 32 | if (i == to) 33 | { 34 | return true; 35 | } 36 | } 37 | } 38 | } 39 | return false; 40 | } 41 | public: 42 | explicit Graph(int vv) 43 | { 44 | v = vv + 1; 45 | pre = new int[v]; 46 | cf = new int*[v]; 47 | for (int i = 0; i < v; i++) 48 | { 49 | cf[i] = new int[v]; 50 | for (int j = 0; j < v; j++) 51 | { 52 | cf[i][j] = 0; 53 | } 54 | } 55 | } 56 | ~Graph() 57 | { 58 | delete[] pre; 59 | for (int i = 0; i < v; i++) 60 | { 61 | delete[] cf[i]; 62 | } 63 | delete[] cf; 64 | } 65 | void AddEdge(int from, int to, int val) 66 | { 67 | cf[from][to] = val; 68 | } 69 | int MaxFlow(int from, int to) 70 | { 71 | int ans = 0; 72 | while (BFS(from, to)) 73 | { 74 | int c = cf[pre[to]][to]; 75 | for (int u = to; u != from; u = pre[u]) 76 | { 77 | c = std::min(c, cf[pre[u]][u]); 78 | } 79 | ans += c; 80 | for (int u = to; u != from; u = pre[u]) 81 | { 82 | cf[pre[u]][u] -= c; 83 | cf[u][pre[u]] += c; 84 | } 85 | } 86 | return ans; 87 | } 88 | }; 89 | 90 | int main() 91 | { 92 | int n, m, u, v, w; 93 | std::cin >> n >> m; 94 | Graph graph(n); 95 | for (int i = 0; i < m; i++) 96 | { 97 | std::cin >> u >> v >> w; 98 | graph.AddEdge(u, v, w); 99 | } 100 | std::cin >> u >> v; 101 | std::cout << graph.MaxFlow(u, v); 102 | return 0; 103 | } -------------------------------------------------------------------------------- /lab4/Flow/shortest.cpp: -------------------------------------------------------------------------------- 1 | // Shortest version(Edmonds-Karp) 2 | #include 3 | #include 4 | 5 | class Graph 6 | { 7 | private: 8 | int v; 9 | int* pre; 10 | int** cf; 11 | private: 12 | // Use BFS to find the shortest path 13 | bool BFS(int from, int to) 14 | { 15 | for (int i = 0; i < v; i++) 16 | { 17 | pre[i] = -1; 18 | } 19 | pre[from] = from; 20 | std::queue q; 21 | q.push(from); 22 | while (!q.empty()) 23 | { 24 | int u = q.front(); 25 | q.pop(); 26 | for (int i = 1; i < v; i++) 27 | { 28 | if (cf[u][i] > 0 && pre[i] == -1) 29 | { 30 | pre[i] = u; 31 | q.push(i); 32 | if (i == to) 33 | { 34 | return true; 35 | } 36 | } 37 | } 38 | } 39 | return false; 40 | } 41 | public: 42 | explicit Graph(int vv) 43 | { 44 | v = vv + 1; 45 | pre = new int[v]; 46 | cf = new int*[v]; 47 | for (int i = 0; i < v; i++) 48 | { 49 | cf[i] = new int[v]; 50 | for (int j = 0; j < v; j++) 51 | { 52 | cf[i][j] = 0; 53 | } 54 | } 55 | } 56 | ~Graph() 57 | { 58 | delete[] pre; 59 | for (int i = 0; i < v; i++) 60 | { 61 | delete[] cf[i]; 62 | } 63 | delete[] cf; 64 | } 65 | void AddEdge(int from, int to, int val) 66 | { 67 | cf[from][to] = val; 68 | } 69 | int MaxFlow(int from, int to) 70 | { 71 | int ans = 0; 72 | while (BFS(from, to)) 73 | { 74 | int c = cf[pre[to]][to]; 75 | for (int u = to; u != from; u = pre[u]) 76 | { 77 | c = std::min(c, cf[pre[u]][u]); 78 | } 79 | ans += c; 80 | for (int u = to; u != from; u = pre[u]) 81 | { 82 | cf[pre[u]][u] -= c; 83 | cf[u][pre[u]] += c; 84 | } 85 | } 86 | return ans; 87 | } 88 | }; 89 | 90 | int main() 91 | { 92 | int n, m, u, v, w; 93 | std::cin >> n >> m; 94 | Graph graph(n); 95 | for (int i = 0; i < m; i++) 96 | { 97 | std::cin >> u >> v >> w; 98 | graph.AddEdge(u, v, w); 99 | } 100 | std::cin >> u >> v; 101 | std::cout << graph.MaxFlow(u, v); 102 | return 0; 103 | } -------------------------------------------------------------------------------- /lab4/Flow/最大流.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab4/Flow/最大流.pdf -------------------------------------------------------------------------------- /lab4/MST/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21) 2 | project(MST) 3 | 4 | add_definitions(-DDEBUG) 5 | 6 | set(CMAKE_CXX_STANDARD 14) 7 | 8 | add_executable(MST 9 | mst.cpp) 10 | -------------------------------------------------------------------------------- /lab4/MST/mst.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | constexpr int maxInt = std::numeric_limits::max(); 7 | 8 | class Graph 9 | { 10 | private: 11 | class Edge 12 | { 13 | public: 14 | int to; 15 | int val; 16 | public: 17 | Edge(int _to, int _val) : to(_to), val(_val) {} 18 | ~Edge() = default; 19 | }; 20 | class Node 21 | { 22 | public: 23 | int index; 24 | int dis; 25 | public: 26 | Node(int _index, int _dis = maxInt) : index(_index), dis(_dis) {} 27 | ~Node() = default; 28 | bool operator<(Node other) const 29 | { 30 | return dis > other.dis; 31 | } 32 | }; 33 | int v; 34 | std::vector* edge; 35 | std::priority_queue heap; 36 | bool* vis; 37 | int* dis; 38 | int** longest; 39 | bool** inTree; 40 | int* pre; 41 | int mst; 42 | private: 43 | void AddEdge(int from, int to, int val) 44 | { 45 | edge[from].emplace_back(to, val); 46 | #ifdef DEBUG 47 | std::cout << "Add edge (" << from << ", " << to << ", " << val << ")" << std::endl; 48 | #endif 49 | } 50 | void Prim() 51 | { 52 | while (!heap.empty()) 53 | { 54 | heap.pop(); 55 | } 56 | for (int i = 0; i < v; i++) 57 | { 58 | vis[i] = false; 59 | dis[i] = maxInt; 60 | } 61 | int cnt = 1; 62 | mst = 0; 63 | heap.push(Node(1, 0)); 64 | dis[1] = 0; 65 | 66 | while (!heap.empty() && cnt < v) 67 | { 68 | int j = heap.top().index; 69 | int d = heap.top().dis; 70 | #ifdef DEBUG 71 | std::cout << "/******************/" << std::endl; 72 | std::cout << "heap.top = (" << j << ", " << d << ")" << std::endl; 73 | std::cout << "/******************/" << std::endl; 74 | #endif 75 | heap.pop(); 76 | if (!vis[j]) 77 | { 78 | vis[j] = true; 79 | cnt += 1; 80 | mst += d; 81 | inTree[pre[j]][j] = inTree[j][pre[j]] = true; 82 | for (int i = 1; i < v; i++) 83 | { 84 | if (vis[i] && i != j) 85 | { 86 | longest[j][i] = longest[i][j] = std::max(longest[pre[j]][i], d); 87 | } 88 | } 89 | for (Edge& u : edge[j]) 90 | { 91 | if (u.val < dis[u.to]) 92 | { 93 | dis[u.to] = u.val; 94 | heap.push(Node(u.to, u.val)); 95 | #ifdef DEBUG 96 | std::cout << "/******************/" << std::endl; 97 | std::cout << "heap.push(" << u.to << ", " << u.val << ")" << std::endl; 98 | std::cout << "/******************/" << std::endl; 99 | #endif 100 | pre[u.to] = j; 101 | } 102 | } 103 | } 104 | } 105 | } 106 | public: 107 | explicit Graph(int _v) 108 | { 109 | v = _v + 1; 110 | edge = new std::vector[v]; 111 | vis = new bool[v]; 112 | dis = new int[v]; 113 | longest = new int*[v]; 114 | inTree = new bool*[v]; 115 | pre = new int[v]; 116 | for (int i = 0; i < v; i++) 117 | { 118 | longest[i] = new int[v]; 119 | inTree[i] = new bool[v]; 120 | } 121 | mst = 0; 122 | } 123 | ~Graph() 124 | { 125 | delete[] edge; 126 | delete[] dis; 127 | delete[] vis; 128 | for (int i = 1; i < v; i++) 129 | { 130 | delete[] longest[i]; 131 | delete[] inTree[i]; 132 | } 133 | delete[] longest; 134 | delete[] inTree; 135 | delete[] pre; 136 | } 137 | void AddEdge(std::istream& in, int edgeCount) 138 | { 139 | int a, b, c; 140 | for (int i = 0; i < edgeCount; i++) 141 | { 142 | in >> a >> b >> c; 143 | AddEdge(a, b, c); 144 | AddEdge(b, a, c); 145 | } 146 | } 147 | 148 | void Solve(std::ostream& out) 149 | { 150 | Prim(); 151 | out << mst << std::endl; 152 | int df = maxInt; 153 | #ifdef DEBUG 154 | std::cout << "/******************/" << std::endl; 155 | for (int i = 1; i < v; i++) 156 | { 157 | for (int j = 1; j < v; j++) 158 | { 159 | out << "longest[" << i << "][" << j << "] = " << longest[i][j] << std::endl; 160 | } 161 | } 162 | std::cout << "/******************/" << std::endl; 163 | #endif 164 | for (int i = 1; i < v; i++) 165 | { 166 | for (Edge& p : edge[i]) 167 | { 168 | if (!inTree[i][p.to]) 169 | { 170 | df = std::min(df, p.val - longest[i][p.to]); 171 | } 172 | } 173 | } 174 | out << mst + df << std::endl; 175 | } 176 | }; 177 | 178 | int main() 179 | { 180 | int n, m; 181 | std::cin >> n >> m; 182 | Graph graph(n); 183 | graph.AddEdge(std::cin, m); 184 | graph.Solve(std::cout); 185 | return 0; 186 | } -------------------------------------------------------------------------------- /lab4/MST/次小生成树.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab4/MST/次小生成树.pdf -------------------------------------------------------------------------------- /lab4/lab4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab4/lab4.pdf -------------------------------------------------------------------------------- /lab4/report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab4/report.pdf -------------------------------------------------------------------------------- /lab5/Circle/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21) 2 | project(Circle) 3 | 4 | add_definitions(-DDEBUG) 5 | 6 | set(CMAKE_CXX_STANDARD 17) 7 | 8 | add_executable(Circle circle.cpp) 9 | -------------------------------------------------------------------------------- /lab5/Circle/circle.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | class Graph 6 | { 7 | private: 8 | class Edge 9 | { 10 | public: 11 | int to; 12 | int val; 13 | static constexpr int maxVal = 0x3fffffff; 14 | public: 15 | Edge(int _to, int _val) 16 | { 17 | to = _to; 18 | val = _val; 19 | } 20 | }; 21 | int v; 22 | std::vector* edge; 23 | int** dp; 24 | private: 25 | void CalPath() 26 | { 27 | for (int i = 1; i < v; i++) 28 | { 29 | AddEdge(0, i, 0); 30 | } 31 | for (int i = 0; i < v; i++) 32 | { 33 | for (int j = 0; j < v; j++) 34 | { 35 | dp[i][j] = Edge::maxVal; 36 | } 37 | } 38 | dp[0][0] = 0; 39 | for (int i = 1; i < v; i++) 40 | { 41 | for (int j = 0; j < v; j++) 42 | { 43 | for (auto& e : edge[j]) 44 | { 45 | dp[i][e.to] = std::min(dp[i - 1][j] + e.val, dp[i][e.to]); 46 | } 47 | } 48 | } 49 | } 50 | public: 51 | explicit Graph(int n) 52 | { 53 | v = n + 1; 54 | edge = new std::vector[v]; 55 | dp = new int*[v]; 56 | for (int i = 0; i < v; i++) 57 | { 58 | dp[i] = new int[v]; 59 | } 60 | } 61 | ~Graph() 62 | { 63 | delete[] edge; 64 | for (int i = 0; i < v; i++) 65 | { 66 | delete[] dp[i]; 67 | } 68 | delete[] dp; 69 | } 70 | void AddEdge(int from, int to, int val) 71 | { 72 | edge[from].emplace_back(to, val); 73 | } 74 | float MinAvgCircle() 75 | { 76 | CalPath(); 77 | #ifdef DEBUG 78 | std::cout << "/******************/" << std::endl << "\t"; 79 | for (int i = 0; i < v; i++) 80 | { 81 | std::cout << i << "\t"; 82 | } 83 | std::cout << std::endl; 84 | for (int i = 0; i < v; i++) 85 | { 86 | std::cout << i << "\t"; 87 | for (int j = 0; j < v; j++) 88 | { 89 | std::cout << (dp[i][j] == Edge::maxVal ? -1 : dp[i][j]) << "\t"; 90 | } 91 | std::cout << std::endl; 92 | } 93 | std::cout << "/******************/" << std::endl; 94 | #endif 95 | auto ans = (float)Edge::maxVal; 96 | float avg = 0; 97 | for (int i = 0; i < v; i++) 98 | { 99 | if (dp[v - 1][i] == Edge::maxVal) 100 | { 101 | continue; 102 | } 103 | for (int j = 0; j < v; j++) 104 | { 105 | avg = std::max(avg, (float)(dp[v - 1][i] - dp[j][i]) / (float)(v - j - 1)); 106 | } 107 | ans = std::min(ans, avg); 108 | avg = 0; 109 | } 110 | return ans; 111 | } 112 | }; 113 | 114 | int main() 115 | { 116 | int n, e, u, v, w; 117 | std::cin >> n >> e; 118 | Graph g(n); 119 | for (int i = 0; i < e; i++) 120 | { 121 | std::cin >> u >> v >> w; 122 | g.AddEdge(u, v, w); 123 | } 124 | std::cout << std::fixed << std::setprecision(3) << g.MinAvgCircle(); 125 | return 0; 126 | } -------------------------------------------------------------------------------- /lab5/Circle/最小平均权重环.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab5/Circle/最小平均权重环.pdf -------------------------------------------------------------------------------- /lab5/Match/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21) 2 | project(Match) 3 | 4 | add_definitions(-DDEBUG) 5 | 6 | set(CMAKE_CXX_STANDARD 17) 7 | 8 | add_executable(Match match.cpp) 9 | -------------------------------------------------------------------------------- /lab5/Match/match.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | class Graph 6 | { 7 | private: 8 | int s, t, v; 9 | int* pre; 10 | int** cf; 11 | int** weight; 12 | private: 13 | bool BFS(int from, int to) 14 | { 15 | for (int i = 0; i < v; i++) 16 | { 17 | pre[i] = -1; 18 | } 19 | pre[from] = from; 20 | std::priority_queue, std::vector>, std::greater<>> q; 21 | q.push(std::make_pair(0, from)); 22 | while (!q.empty()) 23 | { 24 | int u = q.top().second; 25 | q.pop(); 26 | for (int i = 1; i < v; i++) 27 | { 28 | if (cf[u][i] > 0 && pre[i] == -1) 29 | { 30 | pre[i] = u; 31 | q.push(std::make_pair(weight[u][i], i)); 32 | if (i == to) 33 | { 34 | return true; 35 | } 36 | } 37 | } 38 | } 39 | return false; 40 | } 41 | public: 42 | explicit Graph(int _s, int _t) 43 | { 44 | s = _s; 45 | t = _t; 46 | v = s + t + 2; 47 | pre = new int[v]; 48 | cf = new int*[v]; 49 | for (int i = 0; i < v; i++) 50 | { 51 | cf[i] = new int[v]; 52 | for (int j = 0; j < v; j++) 53 | { 54 | cf[i][j] = 0; 55 | } 56 | } 57 | weight = new int*[v]; 58 | for (int i = 0; i < v; i++) 59 | { 60 | weight[i] = new int[v]; 61 | for (int j = 0; j < v; j++) 62 | { 63 | weight[i][j] = 0; 64 | } 65 | } 66 | } 67 | ~Graph() 68 | { 69 | delete[] pre; 70 | for (int i = 0; i < v; i++) 71 | { 72 | delete[] cf[i]; 73 | } 74 | delete[] cf; 75 | for (int i = 0; i < v; i++) 76 | { 77 | delete[] weight[i]; 78 | } 79 | delete[] weight; 80 | } 81 | void AddEdge(int from, int to, int val) 82 | { 83 | cf[from][to] = 1; 84 | weight[from][to] = val; 85 | weight[to][from] = -val; 86 | } 87 | std::pair MaxFlow(int from, int to) 88 | { 89 | for (int i = 1; i <= s; i++) 90 | { 91 | AddEdge(from, i, 0); 92 | } 93 | for (int i = s + 1; i < to; i++) 94 | { 95 | AddEdge(i, to, 0); 96 | } 97 | int ans = 0; 98 | int w = 0; 99 | while (BFS(from, to)) 100 | { 101 | ans += 1; 102 | for (int u = to; u != from; u = pre[u]) 103 | { 104 | cf[pre[u]][u] -= 1; 105 | cf[u][pre[u]] += 1; 106 | w += weight[pre[u]][u]; 107 | } 108 | } 109 | return std::make_pair(ans, w); 110 | } 111 | }; 112 | 113 | int main() 114 | { 115 | int s, t, m, u, v, c; 116 | std::cin >> s >> t >> m; 117 | Graph g(s, t); 118 | for (int i = 0; i < m; i++) 119 | { 120 | std::cin >> u >> v >> c; 121 | g.AddEdge(u, v, c); 122 | } 123 | auto ans = g.MaxFlow(0, s + t + 1); 124 | std::cout << ans.first << " " << ans.second << std::endl; 125 | return 0; 126 | } -------------------------------------------------------------------------------- /lab5/Match/最小权最大匹配.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab5/Match/最小权最大匹配.pdf -------------------------------------------------------------------------------- /lab5/Substr/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21) 2 | project(Substr) 3 | 4 | add_definitions(-DDEBUG) 5 | 6 | set(CMAKE_CXX_STANDARD 17) 7 | 8 | add_executable(Substr substr.cpp) 9 | -------------------------------------------------------------------------------- /lab5/Substr/substr.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class Solution 4 | { 5 | private: 6 | int n; 7 | char* str; 8 | int* p; 9 | private: 10 | void Prefix() 11 | { 12 | p[0] = -1; 13 | for (int k = -1, q = 1; q < n; q++) 14 | { 15 | while (k >= 0 && str[k + 1] != str[q]) 16 | { 17 | k = p[k]; 18 | } 19 | if (str[k + 1] == str[q]) 20 | { 21 | k += 1; 22 | } 23 | p[q] = k; 24 | } 25 | #ifdef DEBUG 26 | std::cout << "/******************/" << std::endl; 27 | for (int i = 0; i < n; i++) 28 | { 29 | std::cout << p[i] << " "; 30 | } 31 | std::cout << std::endl << "/******************/" << std::endl; 32 | #endif 33 | } 34 | public: 35 | Solution(int nn, std::istream& in) 36 | { 37 | n = nn; 38 | str = new char[n + 1]; 39 | p = new int[n]; 40 | in >> str; 41 | } 42 | ~Solution() 43 | { 44 | delete[] str; 45 | delete[] p; 46 | } 47 | void PrintAnswer(std::ostream& out) 48 | { 49 | Prefix(); 50 | int m = 1; 51 | if (n % (n - p[n - 1] - 1) == 0) 52 | { 53 | m = n / (n - p[n - 1] - 1); 54 | } 55 | for (int i = 1; i <= m; i++) 56 | { 57 | if (m % i == 0) 58 | { 59 | out << i << std::endl; 60 | } 61 | } 62 | } 63 | }; 64 | 65 | int main() 66 | { 67 | int n; 68 | std::cin >> n; 69 | Solution solution(n, std::cin); 70 | solution.PrintAnswer(std::cout); 71 | return 0; 72 | } -------------------------------------------------------------------------------- /lab5/Substr/重复子串因子.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab5/Substr/重复子串因子.pdf -------------------------------------------------------------------------------- /lab5/Tail/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21) 2 | project(Tail) 3 | project(Tail_small) 4 | 5 | add_definitions(-DDEBUG) 6 | #add_definitions(-DBIGINTDEBUG) 7 | add_definitions(-DFILEREAD) 8 | 9 | set(CMAKE_CXX_STANDARD 17) 10 | 11 | add_executable(Tail 12 | tail.cpp) 13 | 14 | add_executable(Tail_small 15 | tail_small.cpp) -------------------------------------------------------------------------------- /lab5/Tail/ans.out: -------------------------------------------------------------------------------- 1 | /******************/ 2 | M = 16206557367 3 | /******************/ 4 | /******************/ 5 | M[0] = 5402185789 6 | t[0] = 1 7 | r[0] = 2 8 | p[0] = 3 9 | Inverse Decision Pass! 10 | /******************/ 11 | 0 + mul(above) = 10804371578 12 | /******************/ 13 | M[1] = 2315222481 14 | t[1] = 3 15 | r[1] = 6 16 | p[1] = 7 17 | Inverse Decision Pass! 18 | /******************/ 19 | 10804371578 + mul(above) = 52478376236 20 | /******************/ 21 | M[2] = 1473323397 22 | t[2] = 8 23 | r[2] = 5 24 | p[2] = 11 25 | Inverse Decision Pass! 26 | /******************/ 27 | 52478376236 + mul(above) = 111411312116 28 | /******************/ 29 | M[3] = 1246658259 30 | t[3] = 7 31 | r[3] = 3 32 | p[3] = 13 33 | Inverse Decision Pass! 34 | /******************/ 35 | 111411312116 + mul(above) = 137591135555 36 | /******************/ 37 | M[4] = 704632929 38 | t[4] = 10 39 | r[4] = 9 40 | p[4] = 23 41 | Inverse Decision Pass! 42 | /******************/ 43 | 137591135555 + mul(above) = 201008099165 44 | /******************/ 45 | M[5] = 274687413 46 | t[5] = 22 47 | r[5] = 11 48 | p[5] = 59 49 | Inverse Decision Pass! 50 | /******************/ 51 | 201008099165 + mul(above) = 267482453111 52 | /******************/ 53 | M[6] = 167077911 54 | t[6] = 42 55 | r[6] = 56 56 | p[6] = 97 57 | Inverse Decision Pass! 58 | /******************/ 59 | 267482453111 + mul(above) = 660449699783 60 | /******************/ 61 | M[7] = 395281887 62 | t[7] = 30 63 | r[7] = 40 64 | p[7] = 41 65 | Inverse Decision Pass! 66 | /******************/ 67 | 660449699783 + mul(above) = 1134787964183 68 | 328948493 -------------------------------------------------------------------------------- /lab5/Tail/res.out: -------------------------------------------------------------------------------- 1 | /******************/ 2 | M = 16206557367 3 | /******************/ 4 | /******************/ 5 | M[0] = 5402185789 6 | t[0] = 1 7 | r[0] = 2 8 | p[0] = 3 9 | Inverse Decision Pass! 10 | /******************/ 11 | 0 + mul(above) = (10804371578) 12 | 10804371578 13 | /******************/ 14 | M[1] = 2315222481 15 | t[1] = 3 16 | r[1] = 6 17 | p[1] = 7 18 | Inverse Decision Pass! 19 | /******************/ 20 | 10804371578 + mul(above) = (41674004658) 21 | 52478376236 22 | /******************/ 23 | M[2] = 1473323397 24 | t[2] = 8 25 | r[2] = 5 26 | p[2] = 11 27 | Inverse Decision Pass! 28 | /******************/ 29 | 52478376236 + mul(above) = (58932935880) 30 | 111411312116 31 | /******************/ 32 | M[3] = 1246658259 33 | t[3] = 7 34 | r[3] = 3 35 | p[3] = 13 36 | Inverse Decision Pass! 37 | /******************/ 38 | 111411312116 + mul(above) = (26179823439) 39 | 137591135555 40 | /******************/ 41 | M[4] = 704632929 42 | t[4] = 10 43 | r[4] = 9 44 | p[4] = 23 45 | Inverse Decision Pass! 46 | /******************/ 47 | 137591135555 + mul(above) = (63416963610) 48 | 201008099165 49 | /******************/ 50 | M[5] = 274687413 51 | t[5] = 22 52 | r[5] = 11 53 | p[5] = 59 54 | Inverse Decision Pass! 55 | /******************/ 56 | 201008099165 + mul(above) = (66474353946) 57 | 267482453111 58 | /******************/ 59 | M[6] = 167077911 60 | t[6] = 42 61 | r[6] = 56 62 | p[6] = 97 63 | Inverse Decision Pass! 64 | /******************/ 65 | 267482453111 + mul(above) = (3392967246672) 66 | 960449699783 67 | /******************/ 68 | M[7] = 395281887 69 | t[7] = 30 70 | r[7] = 40 71 | p[7] = 41 72 | /******************/ 73 | 960449699783 + mul(above) = (874338264400) 74 | 1834787964183 75 | 3446981712 -------------------------------------------------------------------------------- /lab5/Tail/tail.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Integer 5 | { 6 | private: 7 | static constexpr unsigned int maxSize = 25000; 8 | unsigned int n; 9 | unsigned int arr[maxSize]{}; 10 | Integer& operator()(const int other) 11 | { 12 | if ((n == 1 && arr[0] == 0) || other == 0) 13 | { 14 | return *this; 15 | } 16 | if (other > 0) 17 | { 18 | for (int i = (int)n - 1; i >= 0; i--) 19 | { 20 | arr[i + other] = arr[i]; 21 | } 22 | for (int i = 0; i < other; i++) 23 | { 24 | arr[i] = 0; 25 | } 26 | n += other; 27 | } 28 | else 29 | { 30 | for (int i = 0; i < n; i++) 31 | { 32 | arr[i] = arr[i - other]; 33 | } 34 | n += other; 35 | } 36 | return *this; 37 | } 38 | static unsigned int Pow(Integer a, unsigned int b, unsigned int mod) 39 | { 40 | unsigned int ans = 1; 41 | unsigned int aa = a % mod; 42 | while (b != 0) 43 | { 44 | if (b & 1) 45 | { 46 | ans = aa * ans % mod; 47 | } 48 | aa = aa * aa % mod; 49 | b >>= 1; 50 | } 51 | return ans; 52 | } 53 | public: 54 | explicit Integer(long long integer = 0) 55 | { 56 | n = 1; 57 | for (auto& i : arr) 58 | { 59 | i = integer % 10; 60 | integer /= 10; 61 | if (integer != 0) 62 | { 63 | n += 1; 64 | } 65 | } 66 | } 67 | static unsigned int Inverse(const Integer& a, const unsigned int mod) 68 | { 69 | return Integer::Pow(a, mod - 2, mod); 70 | } 71 | bool operator<(const Integer& other) const 72 | { 73 | if (n < other.n) 74 | { 75 | return true; 76 | } 77 | if (n > other.n) 78 | { 79 | return false; 80 | } 81 | for (int i = (int)n; i >= 0; i--) 82 | { 83 | if (arr[i] < other.arr[i]) 84 | { 85 | return true; 86 | } 87 | if (arr[i] > other.arr[i]) 88 | { 89 | return false; 90 | } 91 | } 92 | return false; 93 | } 94 | bool operator<=(const Integer& other) const 95 | { 96 | if (this == &other) 97 | { 98 | return true; 99 | } 100 | if (n < other.n) 101 | { 102 | return true; 103 | } 104 | if (n > other.n) 105 | { 106 | return false; 107 | } 108 | for (int i = (int)n; i >= 0; i--) 109 | { 110 | if (arr[i] < other.arr[i]) 111 | { 112 | return true; 113 | } 114 | if (arr[i] > other.arr[i]) 115 | { 116 | return false; 117 | } 118 | } 119 | return true; 120 | } 121 | Integer operator+(const Integer& other) const 122 | { 123 | Integer ans; 124 | int top = (int)std::max(other.n, n); 125 | ans.n = top + 1; 126 | ans.arr[0] = 0; 127 | for (int i = 0; i < top; i++) 128 | { 129 | ans.arr[i + 1] = (ans.arr[i] + arr[i] + other.arr[i]) / 10; 130 | ans.arr[i] = (ans.arr[i] + arr[i] + other.arr[i]) % 10; 131 | } 132 | while (ans.arr[ans.n - 1] == 0 && ans.n > 1) 133 | { 134 | ans.n -= 1; 135 | } 136 | return ans; 137 | } 138 | Integer operator*(const Integer& other) const 139 | { 140 | Integer ans; 141 | ans.n = other.n + n; 142 | for (auto& i : ans.arr) 143 | { 144 | i = 0; 145 | } 146 | for (int i = 0; i < n; i++) 147 | { 148 | for (int j = 0; j < other.n; j++) 149 | { 150 | ans.arr[i + j] += arr[i] * other.arr[j]; 151 | ans.arr[i + j + 1] += ans.arr[i + j] / 10; 152 | ans.arr[i + j] %= 10; 153 | } 154 | } 155 | while (ans.arr[ans.n - 1] == 0 && ans.n > 1) 156 | { 157 | ans.n -= 1; 158 | } 159 | return ans; 160 | } 161 | Integer operator*(const unsigned int other) const 162 | { 163 | Integer ans(0); 164 | for (int i = 0; i < n; i++) 165 | { 166 | ans.arr[i] = arr[i] * other; 167 | } 168 | for (int i = 0; i < n - 1; i++) 169 | { 170 | ans.arr[i + 1] += ans.arr[i] / 10; 171 | ans.arr[i] %= 10; 172 | } 173 | ans.n = n; 174 | while (ans.arr[ans.n - 1] >= 10) 175 | { 176 | ans.arr[ans.n] = ans.arr[ans.n - 1] / 10; 177 | ans.arr[ans.n - 1] %= 10; 178 | ans.n += 1; 179 | } 180 | return ans; 181 | } 182 | Integer operator/(const unsigned int other) const 183 | { 184 | Integer ans(0); 185 | unsigned int tmp = 0; 186 | for (int i = (int)n - 1; i >= 0; i--) 187 | { 188 | tmp *= 10; 189 | tmp += arr[i]; 190 | ans.arr[i] = tmp / other; 191 | tmp %= other; 192 | if (ans.arr[i] != 0 && ans.n == 1) 193 | { 194 | ans.n = i + 1; 195 | } 196 | } 197 | return ans; 198 | } 199 | unsigned int operator%(const unsigned int other) const 200 | { 201 | unsigned int tmp = 0; 202 | for (int i = (int)n - 1; i >= 0; i--) 203 | { 204 | tmp *= 10; 205 | tmp += arr[i]; 206 | tmp %= other; 207 | } 208 | return tmp; 209 | } 210 | Integer operator%(Integer other) const 211 | { 212 | Integer ans = *this; 213 | int depth = (int)(n - other.n); 214 | other(depth); 215 | while (depth >= 0) 216 | { 217 | while (other <= ans) 218 | { 219 | ans -= other; 220 | } 221 | depth -= 1; 222 | other(-1); 223 | } 224 | return ans; 225 | } 226 | Integer& operator=(unsigned int other) 227 | { 228 | n = 1; 229 | for (auto& i : arr) 230 | { 231 | i = other % 10; 232 | other /= 10; 233 | if (other != 0) 234 | { 235 | n += 1; 236 | } 237 | } 238 | return *this; 239 | } 240 | Integer& operator=(const Integer& other) 241 | { 242 | if (this == &other) 243 | { 244 | return *this; 245 | } 246 | n = other.n; 247 | for (int i = 0; i < maxSize; i++) 248 | { 249 | arr[i] = other.arr[i]; 250 | } 251 | return *this; 252 | } 253 | Integer& operator+=(const Integer& other) 254 | { 255 | int top = (int)std::max(other.n, n); 256 | n = top + 1; 257 | for (int i = 0; i < top; i++) 258 | { 259 | arr[i] += other.arr[i]; 260 | arr[i + 1] += arr[i] / 10; 261 | arr[i] %= 10; 262 | } 263 | while (arr[n - 1] == 0 && n > 1) 264 | { 265 | n -= 1; 266 | } 267 | return *this; 268 | } 269 | Integer& operator-=(const Integer& other) 270 | { 271 | for (int i = (int)n - 1; i >= 0; i--) 272 | { 273 | arr[i] -= other.arr[i]; 274 | } 275 | for (int i = 0; i < n; i++) 276 | { 277 | if (arr[i] >= 10) 278 | { 279 | arr[i] += 10; 280 | arr[i + 1] -= 1; 281 | } 282 | } 283 | while (arr[n - 1] == 0 && n > 1) 284 | { 285 | n -= 1; 286 | } 287 | return *this; 288 | } 289 | Integer& operator*=(unsigned int other) 290 | { 291 | for (int i = 0; i < n; i++) 292 | { 293 | arr[i] *= other; 294 | } 295 | for (int i = 0; i < n - 1; i++) 296 | { 297 | arr[i + 1] += arr[i] / 10; 298 | arr[i] %= 10; 299 | } 300 | while (arr[n - 1] >= 10) 301 | { 302 | arr[n] = arr[n - 1] / 10; 303 | arr[n - 1] %= 10; 304 | n += 1; 305 | } 306 | return *this; 307 | } 308 | Integer& operator*=(const Integer& other) 309 | { 310 | Integer ans; 311 | ans.n = other.n + n; 312 | for (auto& i : ans.arr) 313 | { 314 | i = 0; 315 | } 316 | for (int i = 0; i < n; i++) 317 | { 318 | for (int j = 0; j < other.n; j++) 319 | { 320 | ans.arr[i + j] += arr[i] * other.arr[j]; 321 | ans.arr[i + j + 1] += ans.arr[i + j] / 10; 322 | ans.arr[i + j] %= 10; 323 | } 324 | } 325 | while (ans.arr[ans.n - 1] == 0 && ans.n > 1) 326 | { 327 | ans.n -= 1; 328 | } 329 | *this = ans; 330 | return *this; 331 | } 332 | friend std::istream& operator>>(std::istream& in, Integer& x) 333 | { 334 | std::string str; 335 | in >> str; 336 | x.n = (int)str.length(); 337 | for (int i = 0; i < x.n; i++) 338 | { 339 | x.arr[i] = str[x.n - i - 1] ^ 48; 340 | } 341 | return in; 342 | } 343 | friend std::ostream& operator<<(std::ostream& out, const Integer& x) 344 | { 345 | for (int i = (int)x.n - 1; i >= 0; i--) 346 | { 347 | out << x.arr[i]; 348 | } 349 | return out; 350 | } 351 | }; 352 | 353 | class Solution 354 | { 355 | private: 356 | int k; 357 | int cnt; 358 | int* r; 359 | int* p; 360 | Integer* m; 361 | public: 362 | explicit Solution(int kk) 363 | { 364 | k = kk; 365 | cnt = 0; 366 | r = new int[k]; 367 | p = new int[k]; 368 | m = new Integer[k]; 369 | } 370 | ~Solution() 371 | { 372 | delete[] r; 373 | delete[] p; 374 | delete[] m; 375 | } 376 | 377 | void AddPair(int rr, int pp) 378 | { 379 | r[cnt] = rr; 380 | p[cnt] = pp; 381 | cnt += 1; 382 | } 383 | 384 | void PrintAnswer(std::ostream& out) const 385 | { 386 | Integer M(1); 387 | for (int i = 0; i < k; i++) 388 | { 389 | M *= p[i]; 390 | } 391 | #ifdef DEBUG 392 | std::cout << "/******************/" << std::endl; 393 | std::cout << "M = " << M << std::endl; 394 | std::cout << "/******************/" << std::endl; 395 | #endif 396 | Integer ans(0); 397 | for (int i = 0; i < k; i++) 398 | { 399 | m[i] = M / p[i]; 400 | #ifdef DEBUG 401 | std::cout << "/******************/" << std::endl; 402 | std::cout << "M[" << i << "] = " << m[i] << std::endl; 403 | unsigned int t = Integer::Inverse(m[i], p[i]); 404 | std::cout << "t[" << i << "] = " << t << std::endl; 405 | std::cout << "r[" << i << "] = " << r[i] << std::endl; 406 | std::cout << "p[" << i << "] = " << p[i] << std::endl; 407 | if (m[i] * t % p[i] == 1) 408 | { 409 | std::cout << "Inverse Decision Pass!" << std::endl; 410 | } 411 | std::cout << "/******************/" << std::endl; 412 | ans += m[i] * t * (unsigned int)r[i]; 413 | std::cout << ans << std::endl; 414 | #else 415 | ans += m[i] * Integer::Inverse(m[i], p[i]) * (unsigned int)r[i]; 416 | #endif 417 | } 418 | out << ans % M; 419 | } 420 | }; 421 | 422 | int main() 423 | { 424 | #ifdef BIGINTDEBUG 425 | Integer x, y; 426 | std::cin >> x >> y; 427 | std::cout << x % y; 428 | return 0; 429 | #endif 430 | #ifdef FILEREAD 431 | std::freopen("../test.in", "r", stdin); 432 | std::freopen("../res.out", "w", stdout); 433 | #endif 434 | int k, r, p; 435 | std::cin >> k; 436 | Solution solution(k); 437 | for (int i = 0; i < k; i++) 438 | { 439 | std::cin >> r >> p; 440 | solution.AddPair(r, p); 441 | } 442 | solution.PrintAnswer(std::cout); 443 | return 0; 444 | } -------------------------------------------------------------------------------- /lab5/Tail/tail_small.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Solution 5 | { 6 | private: 7 | int k; 8 | int cnt; 9 | long long* r; 10 | long long* p; 11 | long long* m; 12 | private: 13 | static long long Pow(long long a, long long b, long long mod) 14 | { 15 | long long ans = 1; 16 | long long aa = a % mod; 17 | while (b != 0) 18 | { 19 | if (b & 1) 20 | { 21 | ans = aa * ans % mod; 22 | } 23 | aa = aa * aa % mod; 24 | b >>= 1; 25 | } 26 | return ans; 27 | } 28 | static long long Inverse(long long a, long long mod) 29 | { 30 | return Pow(a, mod - 2, mod); 31 | } 32 | public: 33 | explicit Solution(int kk) 34 | { 35 | k = kk; 36 | cnt = 0; 37 | r = new long long[k]; 38 | p = new long long[k]; 39 | m = new long long[k]; 40 | } 41 | ~Solution() 42 | { 43 | delete[] r; 44 | delete[] p; 45 | delete[] m; 46 | } 47 | 48 | void AddPair(int rr, int pp) 49 | { 50 | r[cnt] = rr; 51 | p[cnt] = pp; 52 | cnt += 1; 53 | } 54 | 55 | void PrintAnswer(std::ostream& out) const 56 | { 57 | long long M = 1; 58 | for (int i = 0; i < k; i++) 59 | { 60 | M *= p[i]; 61 | } 62 | #ifdef DEBUG 63 | std::cout << "/******************/" << std::endl; 64 | std::cout << "M = " << M << std::endl; 65 | std::cout << "/******************/" << std::endl; 66 | #endif 67 | long long ans = 0; 68 | for (int i = 0; i < k; i++) 69 | { 70 | m[i] = M / p[i]; 71 | #ifdef DEBUG 72 | std::cout << "/******************/" << std::endl; 73 | std::cout << "M[" << i << "] = " << m[i] << std::endl; 74 | long long t = Inverse(m[i], p[i]); 75 | std::cout << "t[" << i << "] = " << t << std::endl; 76 | std::cout << "r[" << i << "] = " << r[i] << std::endl; 77 | std::cout << "p[" << i << "] = " << p[i] << std::endl; 78 | if (m[i] * t % p[i] == 1) 79 | { 80 | std::cout << "Inverse Decision Pass!" << std::endl; 81 | } 82 | std::cout << "/******************/" << std::endl; 83 | std::cout << ans << " + mul(above) = "; 84 | ans += m[i] * t * (long long)r[i]; 85 | std::cout << ans << std::endl; 86 | #else 87 | ans += m[i] * Inverse(m[i], p[i]) * (long long)r[i]; 88 | #endif 89 | } 90 | out << ans % M; 91 | } 92 | }; 93 | 94 | int main() 95 | { 96 | #ifdef BIGINTDEBUG 97 | Integer x, y; 98 | std::cin >> x >> y; 99 | std::cout << x % y; 100 | return 0; 101 | #endif 102 | #ifdef FILEREAD 103 | std::freopen("../test.in", "r", stdin); 104 | std::freopen("../ans.out", "w", stdout); 105 | #endif 106 | int k, r, p; 107 | std::cin >> k; 108 | Solution solution(k); 109 | for (int i = 0; i < k; i++) 110 | { 111 | std::cin >> r >> p; 112 | solution.AddPair(r, p); 113 | } 114 | solution.PrintAnswer(std::cout); 115 | return 0; 116 | } -------------------------------------------------------------------------------- /lab5/Tail/test.in: -------------------------------------------------------------------------------- 1 | 8 2 | 2 3 3 | 6 7 4 | 5 11 5 | 3 13 6 | 9 23 7 | 11 59 8 | 56 97 9 | 40 41 10 | -------------------------------------------------------------------------------- /lab5/Tail/尾数还原.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab5/Tail/尾数还原.pdf -------------------------------------------------------------------------------- /lab5/lab5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab5/lab5.pdf -------------------------------------------------------------------------------- /lab5/report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/txtxj/USTC-Algorithm/e69c184b0de40f838d09d800dbcee41aa6ed7357/lab5/report.pdf --------------------------------------------------------------------------------