From 38e97654e14910aeedaaca069d74d4dc0ddd0f8c Mon Sep 17 00:00:00 2001 From: rogerwang2008 Date: Mon, 9 Nov 2026 21:13:09 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=80=E5=A7=8B=E8=AE=A1=E6=A6=82A=E4=B8=8B?= =?UTF-8?q?=E5=8D=8A=E5=AD=A6=E6=9C=9F=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 +- .idea/workspace.xml | 597 ++++++++++++++++-- CMakeLists.txt | 6 + _others/others_test.c | 46 +- _others/others_test_cpp.cpp | 84 ++- cs101/2025mid/exam_2025mid_01_digits.cpp | 23 + cs101/2025mid/exam_2025mid_02_mock_exam.cpp | 34 + cs101/2025mid/exam_2025mid_03_clinic_sort.cpp | 38 ++ cs101/2025mid/exam_2025mid_04_bamboo_pole.cpp | 29 + cs101/2025mid/exam_2025mid_05_type_cast.cpp | 57 ++ cs101/2025mid/exam_2025mid_06_perm.cpp | 54 ++ cs101/2025mid/exam_2025mid_07_op.cpp | 20 + cs101/2025mid/exam_2025mid_08_wall_dp.cpp | 43 ++ cs101/2025mid/exam_2025mid_09_bigfloat.cpp | 160 +++++ cs101/stage_3/dh_31_01_teeth_dp.cpp | 26 + cs101/stage_3/dh_31_02_lcm.cpp | 25 + cs101/stage_3/dh_31_03_is_palindromic.cpp | 20 + cs101/stage_3/dh_31_04_kakutani_guess.cpp | 22 + cs101/stage_3/dh_31_05_sunwukong.cpp | 89 +++ .../dh_31_06_legendre_polynomials_dp.cpp | 24 + dsa/ch3_stack_queue/template_queue_linear.cpp | 15 + ...kmp_P3375.cpp => template_kmp_elegent.cpp} | 5 +- dsa/ch4_string/template_kmp_standard_next.cpp | 74 +++ .../dsa_0509_expression_tree.cpp | 224 +++++++ .../dsa_0512_text_binary_tree.cpp | 107 ++++ .../luogu_template_huffman_B2168.cpp | 112 ++++ dsa/ch6_tree/dsa_0603_crime_gangs.cpp | 88 +++ dsa/ch6_tree/dsa_0613_tree_conversion.cpp | 144 +++++ dsa/ch7_graph/template_adjacent_list.cpp | 64 ++ .../template_chained_forward_stare.cpp | 8 + pojcs101_T04117_split_int.cpp | 12 +- 31 files changed, 2144 insertions(+), 110 deletions(-) create mode 100644 cs101/2025mid/exam_2025mid_01_digits.cpp create mode 100644 cs101/2025mid/exam_2025mid_02_mock_exam.cpp create mode 100644 cs101/2025mid/exam_2025mid_03_clinic_sort.cpp create mode 100644 cs101/2025mid/exam_2025mid_04_bamboo_pole.cpp create mode 100644 cs101/2025mid/exam_2025mid_05_type_cast.cpp create mode 100644 cs101/2025mid/exam_2025mid_06_perm.cpp create mode 100644 cs101/2025mid/exam_2025mid_07_op.cpp create mode 100644 cs101/2025mid/exam_2025mid_08_wall_dp.cpp create mode 100644 cs101/2025mid/exam_2025mid_09_bigfloat.cpp create mode 100644 cs101/stage_3/dh_31_01_teeth_dp.cpp create mode 100644 cs101/stage_3/dh_31_02_lcm.cpp create mode 100644 cs101/stage_3/dh_31_03_is_palindromic.cpp create mode 100644 cs101/stage_3/dh_31_04_kakutani_guess.cpp create mode 100644 cs101/stage_3/dh_31_05_sunwukong.cpp create mode 100644 cs101/stage_3/dh_31_06_legendre_polynomials_dp.cpp create mode 100644 dsa/ch3_stack_queue/template_queue_linear.cpp rename dsa/ch4_string/{luogu_template_kmp_P3375.cpp => template_kmp_elegent.cpp} (90%) create mode 100644 dsa/ch4_string/template_kmp_standard_next.cpp create mode 100644 dsa/ch5_binary_tree/dsa_0509_expression_tree.cpp create mode 100644 dsa/ch5_binary_tree/dsa_0512_text_binary_tree.cpp create mode 100644 dsa/ch5_binary_tree/luogu_template_huffman_B2168.cpp create mode 100644 dsa/ch6_tree/dsa_0603_crime_gangs.cpp create mode 100644 dsa/ch6_tree/dsa_0613_tree_conversion.cpp create mode 100644 dsa/ch7_graph/template_adjacent_list.cpp create mode 100644 dsa/ch7_graph/template_chained_forward_stare.cpp diff --git a/.gitignore b/.gitignore index 742acfa..0332797 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,6 @@ cmake-build-debug-gcc !*/ *.dSYM/ -**/*.out \ No newline at end of file +**/*.out + +_no_compile/DSA_Templates diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 07e07cd..e31ab91 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -21,7 +21,9 @@ + + @@ -32,7 +34,10 @@ + + + @@ -46,15 +51,20 @@ + + + - + + + @@ -67,10 +77,13 @@ + + + @@ -90,8 +103,10 @@ + + @@ -107,9 +122,11 @@ + + @@ -125,27 +142,33 @@ + + + + + + @@ -162,6 +185,7 @@ + @@ -171,41 +195,204 @@ + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + @@ -307,6 +495,13 @@ "CMake 应用程序._others__jzh__jzh_c1_h.executor": "Run", "CMake 应用程序._others__others_test.executor": "Run", "CMake 应用程序._others__others_test_cpp.executor": "Run", + "CMake 应用程序.cs101__2025mid__exam_2025mid_02_mock_exam.executor": "Run", + "CMake 应用程序.cs101__2025mid__exam_2025mid_03_clinic_sort.executor": "Run", + "CMake 应用程序.cs101__2025mid__exam_2025mid_05_type_cast.executor": "Run", + "CMake 应用程序.cs101__2025mid__exam_2025mid_06_perm.executor": "Run", + "CMake 应用程序.cs101__2025mid__exam_2025mid_07_op.executor": "Run", + "CMake 应用程序.cs101__2025mid__exam_2025mid_08_wall_dp.executor": "Run", + "CMake 应用程序.cs101__2025mid__exam_2025mid_09_bigfloat.executor": "Run", "CMake 应用程序.cs101__dh_05_01_newton_sqrt.executor": "Run", "CMake 应用程序.cs101__dh_05_02_three_nums.executor": "Run", "CMake 应用程序.cs101__dh_05_04_fried_chicken.executor": "Run", @@ -362,6 +557,11 @@ "CMake 应用程序.cs101__stage_2__dh_16_05_line_wrap.executor": "Run", "CMake 应用程序.cs101__stage_2__dh_16_07_observer_stone.executor": "Run", "CMake 应用程序.cs101__stage_2__dh_16_08_tianji_horse.executor": "Run", + "CMake 应用程序.cs101__stage_3__dh_31_01_teeth_dp.executor": "Run", + "CMake 应用程序.cs101__stage_3__dh_31_02_lcm.executor": "Run", + "CMake 应用程序.cs101__stage_3__dh_31_03_is_palindromic.executor": "Run", + "CMake 应用程序.cs101__stage_3__dh_31_05_sunwukong.executor": "Debug", + "CMake 应用程序.cs101__stage_3__dh_31_06_legendre_polynomials_dp.executor": "Debug", "CMake 应用程序.dp__TJOI2007_walk_segments_dp.executor": "Run", "CMake 应用程序.dp__luogu_U434718_eagle_egg.executor": "Run", "CMake 应用程序.dsa__ch2_linear_list__P2629_good_news.executor": "Run", @@ -375,10 +575,16 @@ "CMake 应用程序.dsa__ch4_string__dsa_0404_string_loop.executor": "Run", "CMake 应用程序.dsa__ch4_string__dsa_0406_valid_string.executor": "Run", "CMake 应用程序.dsa__ch4_string__luogu_template_kmp_P3375.executor": "Run", + "CMake 应用程序.dsa__ch4_string__template_kmp_standard_next.executor": "Run", + "CMake 应用程序.dsa__ch5_binary_tree__dsa_0509_expression_tree.executor": "Run", "CMake 应用程序.dsa__ch5_binary_tree__dsa_0510_reconstruct_tree.executor": "Run", + "CMake 应用程序.dsa__ch5_binary_tree__dsa_0512_text_binary_tree.executor": "Run", "CMake 应用程序.dsa__ch5_binary_tree__dsa_0514_heap_STL.executor": "Run", "CMake 应用程序.dsa__ch5_binary_tree__luogu_P4715_matches.executor": "Run", "CMake 应用程序.dsa__ch5_binary_tree__luogu_T750119_bin_tree_iter.executor": "Run", + "CMake 应用程序.dsa__ch5_binary_tree__luogu_template_huffman_B2168.executor": "Run", + "CMake 应用程序.dsa__ch6_tree__dsa_0603_crime_gangs.executor": "Debug", + "CMake 应用程序.dsa__ch6_tree__dsa_0613_tree_conversion.executor": "Run", "CMake 应用程序.dsa__linear_list__dsa_0201_dictionary.executor": "Run", "CMake 应用程序.dsa__linear_list__dsa_0202_card_stacking.executor": "Run", "CMake 应用程序.dsa__linear_list__dsa_0204_prefix_cycle.executor": "Run", @@ -426,7 +632,7 @@ "codeWithMe.voiceChat.enabledByDefault": "false", "deletionFromPopupRequiresConfirmation": "false", "git-widget-placeholder": "main", - "last_opened_file_path": "/Users/roger/coding/exercises/cs101/stage_2", + "last_opened_file_path": "/Users/roger/coding/exercises/_others", "leon.ai.report.branch": "main", "leon.t.first": "low", "leon.t.source": "auto", @@ -436,7 +642,7 @@ "nodejs_package_manager_path": "npm", "org.rust.first.attach.projects": "true", "python.packages.toolwindow.project.migrated.to.right.top.v2": "true", - "settings.editor.selected.configurable": "preferences.keymap" + "settings.editor.selected.configurable": "fileTemplates" } }]]> @@ -444,21 +650,21 @@ + + - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + @@ -1024,6 +1325,11 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -1908,7 +2390,9 @@ - @@ -1998,11 +2482,6 @@ 11 + + + + + diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c6609c..b3328a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) file(GLOB_RECURSE SOURCES "*.cpp" "*.c") +list(FILTER SOURCES EXCLUDE REGEX ".*/_no_compile/.*") + foreach (source ${SOURCES}) # 获取源文件所在目录(绝对路径) get_filename_component(dir ${source} DIRECTORY) @@ -32,4 +34,8 @@ foreach (source ${SOURCES}) set_target_properties(${target_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${rel_dir}" ) + + target_compile_options(${target_name} PRIVATE + -Wall -Wextra -Wpedantic + ) endforeach () \ No newline at end of file diff --git a/_others/others_test.c b/_others/others_test.c index a6a961b..fe21176 100644 --- a/_others/others_test.c +++ b/_others/others_test.c @@ -1,22 +1,42 @@ #include +int LINE[700000] = {0}; + +void test(int& a) { + a++; +} int main() { - int number = 0, logo = 0; - scanf("%d", &number); - for (int wait_test = 1; wait_test <= number; wait_test++) { - while (logo == 0) { - int same = wait_test; - while (same >= 67) { - int a = same % 100; - if (a == 67) { - printf("%d\n", wait_test); - logo++; - break; + int i = 1; + for (int j = 1; j <= 100000; j++) { + while (LINE[j] == 0) { + int flag = 0; + int transform = i; + if (transform % 7 != 0) { + while (transform > 0) { + if (transform % 10 == 7) { + flag++; + } + transform /= 10; } - same /= 10; + } else { + flag++; + } + if (flag == 0) { + LINE[j] = i; + i++; + } else { + i++; } } - logo--; } + int group = 0; + scanf("%d", &group); + for (int z = 1; z <= group; z++) { + int input = 0; + scanf("%d", &input); + printf("%d\n", LINE[input]); + } + int val = *(LINE+5); + int a=1; return 0; } diff --git a/_others/others_test_cpp.cpp b/_others/others_test_cpp.cpp index e98f371..d8d281e 100644 --- a/_others/others_test_cpp.cpp +++ b/_others/others_test_cpp.cpp @@ -1,54 +1,52 @@ -#include -#include -#include -#include +#include +using namespace std; -constexpr int MAX_N = 1001, MAX_T = 1001; - -struct Attendee { - int enter_time = 0, exit_time = 0; +struct patient { + string id; + int year; }; - -int get_max_attendees_amount(std::vector attendees_schedule) { - std::array bucket {}; - for (const auto [enter_time, exit_time] : attendees_schedule) { - for (int t = enter_time; t < exit_time; t++) { - bucket[t]++; - } - } - return *std::max_element(bucket.begin(), bucket.end()); -} - - int main() { - std::iostream::sync_with_stdio(false); - std::cin.tie(nullptr); + int n; + cin >> n; - std::vector attendees; - char temp_comma; - int x; - while (true) { - std::cin >> x >> temp_comma; - attendees.push_back({x, -1}); - if (temp_comma != ',') { - std::cin.unget(); - break; - } + int num = 0, cnt = 0; + patient p[n]; + patient x[n]; + string young[n]; + for (int i = 0; i < n; i++) { + cin >> p[i].id >> p[i].year; + x[i].id = p[i].id; + x[i].year = p[i].year; } - for (int i = 0; i < attendees.size() - 1; i++) { - std::cin >> attendees[i].exit_time >> temp_comma; - } - std::cin >> attendees[attendees.size() - 1].exit_time; - std::cout << attendees.size() << ' ' << get_max_attendees_amount(attendees) << std::endl; - - int x = 6, ans = 0; - if (x > 5) - if (x > 10) ans = 1; + for (int j = 0; j < n; j++) { + if (p[j].year >= 60) + num++; else - ans = 2; - std::cout << ans; + young[cnt] = p[j].id; + cnt++; + } + for (int i = 0; i < n - 1; i++) + for (int j = 0; j < n - 1 - i; j++) { + int temp_year; + string temp_id; + if (x[j].year < x[j + 1].year) { + temp_year = x[j].year; + temp_id = x[j].id; + x[j].year = x[j + 1].year; + x[j].id = x[j + 1].id; + x[j + 1].year = temp_year; + x[j + 1].id = temp_id; + } + } + + for (int i = 0; i < num; i++) { + cout << x[i].id << endl; + } + for (int j = 0; j < cnt; j++) { + cout << young[j] << endl; + } return 0; } diff --git a/cs101/2025mid/exam_2025mid_01_digits.cpp b/cs101/2025mid/exam_2025mid_01_digits.cpp new file mode 100644 index 0000000..08a8165 --- /dev/null +++ b/cs101/2025mid/exam_2025mid_01_digits.cpp @@ -0,0 +1,23 @@ +#include + +std::size_t calc_digits(std::string num) { + if (num == "0") { return 1; } + std::size_t ans = num.size(), i = 0; + while (num[i] == '0') { + i++; + ans--; + } + return ans; +} + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + + std::string num; + std::cin >> num; + std::cout << calc_digits(num) << std::endl; + + + return 0; +} diff --git a/cs101/2025mid/exam_2025mid_02_mock_exam.cpp b/cs101/2025mid/exam_2025mid_02_mock_exam.cpp new file mode 100644 index 0000000..830e54a --- /dev/null +++ b/cs101/2025mid/exam_2025mid_02_mock_exam.cpp @@ -0,0 +1,34 @@ +#include +#include +#include +#include + +constexpr std::size_t MAX_N = 1001; +int students_amount, task_per_student, total_days; +std::array, MAX_N> arrangements; + + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + + std::cin >> students_amount >> task_per_student >> total_days; + for (int _ = 0; _ < students_amount; _++) { + for (int i = 0; i < task_per_student; i++) { + int day; + std::cin >> day; + arrangements[day][i] = true; + } + } + + bool first = true; + for (int i = 1; i <= total_days; i++) { + if (!first) { std::cout << ' '; } + std::cout << std::count(arrangements[i].begin(), arrangements[i].end(), true); + first = false; + } + + std::cout << std::endl; + + return 0; +} diff --git a/cs101/2025mid/exam_2025mid_03_clinic_sort.cpp b/cs101/2025mid/exam_2025mid_03_clinic_sort.cpp new file mode 100644 index 0000000..e87d9ac --- /dev/null +++ b/cs101/2025mid/exam_2025mid_03_clinic_sort.cpp @@ -0,0 +1,38 @@ +#include +#include +#include + +struct Patient { + int reservation_order = -1; + std::string id; + int age = -1; + + bool operator<(const Patient& other) const { + if (age < 60 && other.age >= 60) { return !(other < *this); } + if (age >= 60) { + if (other.age < 60) { return true; } + if (age == other.age) { return reservation_order < other.reservation_order; } + return age > other.age; + } + return reservation_order < other.reservation_order; + } +}; + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + + int n; + std::cin >> n; + std::vector patients(n); + for (int i = 0; i < n; i++) { + std::cin >> patients[i].id >> patients[i].age; + patients[i].reservation_order = i; + } + std::sort(patients.begin(), patients.end()); + for (const auto& [reservation_order, id, age] : patients) { + std::cout << id << std::endl; + } + + return 0; +} diff --git a/cs101/2025mid/exam_2025mid_04_bamboo_pole.cpp b/cs101/2025mid/exam_2025mid_04_bamboo_pole.cpp new file mode 100644 index 0000000..39c858f --- /dev/null +++ b/cs101/2025mid/exam_2025mid_04_bamboo_pole.cpp @@ -0,0 +1,29 @@ +/* +* 特别处理有一个杆子超级长? + */ + +#include +#include +#include + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + + int n; + std::cin >> n; + + std::vector half_lengths; + half_lengths.reserve(2 * n); + for (int i = 0; i < n; i++) { + int length, flag_pos; + std::cin >> length >> flag_pos; + half_lengths.push_back(length - flag_pos); + half_lengths.push_back(flag_pos); + } + std::sort(half_lengths.begin(), half_lengths.end(), std::greater<>()); + + std::cout << half_lengths[0] + half_lengths[1] << std::endl; + + return 0; +} diff --git a/cs101/2025mid/exam_2025mid_05_type_cast.cpp b/cs101/2025mid/exam_2025mid_05_type_cast.cpp new file mode 100644 index 0000000..e6e5937 --- /dev/null +++ b/cs101/2025mid/exam_2025mid_05_type_cast.cpp @@ -0,0 +1,57 @@ +#include +#include + +const std::unordered_map TYPE_NAME_PRIORITIES = { + {"bool", 0}, + {"char", 1}, + {"int", 2}, + {"longlong", 4}, + {"float", 99}, + {"double", 100}, +}; + +class Type : public std::string { +public: + using std::string::string; + + bool operator<(const Type& other) const { + if (empty()) { return true; } + return TYPE_NAME_PRIORITIES.at(*this) < TYPE_NAME_PRIORITIES.at(other); + } +}; + +void run() { + Type max_type, current_type; + std::string line; + std::cin >> line; + auto comma_pos = line.rfind(','); + if (comma_pos != std::string::npos) { + line.erase(0, comma_pos + 1); + } + for (char c : line) { + if (!std::isalpha(c)) { + std::clog << current_type << c << std::endl; + if (c == ',') { + max_type.clear(); + } else { + if (max_type < Type("int")) { max_type = "int"; } + max_type = std::max(max_type, current_type); + } + current_type.clear(); + } else { + current_type += c; + } + } + max_type = std::max(max_type, current_type); + std::cout << max_type << std::endl; +} + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + int n; + std::cin >> n; + while (n--) { run(); } + + return 0; +} diff --git a/cs101/2025mid/exam_2025mid_06_perm.cpp b/cs101/2025mid/exam_2025mid_06_perm.cpp new file mode 100644 index 0000000..0d352be --- /dev/null +++ b/cs101/2025mid/exam_2025mid_06_perm.cpp @@ -0,0 +1,54 @@ +#include +#include + +bool validate_arithmetic(const std::vector& bucket) { + if (bucket.size() <= 1) { return false; } + int previous_idx = -1, distance = -1; + for (int i = 0; i < bucket.size(); i++) { + if (!bucket[i]) { continue; } + if (previous_idx == -1) { + previous_idx = i; + continue; + } + if (distance == -1) { + distance = i - previous_idx; + } + if (i - previous_idx != distance) { + return false; + } + previous_idx = i; + } + return true; +} + +int clac_ans(const std::vector& nums) { + if (nums.size() == 1) { return 0; } + std::vector bucket_begin(nums.size(), false); + std::vector bucket_end(nums.size(), true); + + int ans = 0; + for (int i = 0; i < nums.size(); i++) { + bucket_begin[nums[i]] = true; + bucket_end[nums[i]] = false; + if (validate_arithmetic(bucket_begin) && validate_arithmetic(bucket_end)) { + ans++; + std::clog << i << std::endl; + } + } + return ans - 1; +} + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + + int n; + std::cin >> n; + while (std::cin >> n) { + std::vector nums(n); + for (int i = 0; i < n; i++) { std::cin >> nums[i], nums[i]--; } + std::cout << clac_ans(nums) << std::endl; + } + + return 0; +} diff --git a/cs101/2025mid/exam_2025mid_07_op.cpp b/cs101/2025mid/exam_2025mid_07_op.cpp new file mode 100644 index 0000000..f4197e1 --- /dev/null +++ b/cs101/2025mid/exam_2025mid_07_op.cpp @@ -0,0 +1,20 @@ +#include +#include + +long long calc_min_ops(long long a, long long b) { + if (a > b) { return a - b; } + long long div = b / a; + auto multiply_times = static_cast(std::log2(div)); + a = a * std::pow(2, multiply_times); + return std::min(multiply_times + b - a, multiply_times + 1 + (2 * a - b)); +} + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + long long a, b; + std::cin >> a >> b; + std::cout << calc_min_ops(a, b) << std::endl; + + return 0; +} diff --git a/cs101/2025mid/exam_2025mid_08_wall_dp.cpp b/cs101/2025mid/exam_2025mid_08_wall_dp.cpp new file mode 100644 index 0000000..0a80108 --- /dev/null +++ b/cs101/2025mid/exam_2025mid_08_wall_dp.cpp @@ -0,0 +1,43 @@ +#include + +constexpr int MAX_N = 1000001, MOD = 10000; + +/// dp[0][i]: 长方形;dp[1][i]: 阶梯型,i 为短边长 +long long dp[2][MAX_N]; + +void init_dp() { + dp[0][0] = 1; + dp[0][1] = 1; + dp[0][2] = 2; + dp[1][0] = 0; + dp[1][1] = 1; + dp[1][2] = 2; + for (int i = 3; i < MAX_N; i++) { + dp[0][i] = (dp[0][i - 1] + dp[0][i - 2] + dp[1][i - 2] * 2) % MOD; + dp[1][i] = (dp[0][i - 1] + dp[1][i - 1]) % MOD; + } +} + +void log_dp(int n) { + for (int i = 1; i <= n; i++) { + std::clog << dp[0][i] << ' '; + } + std::clog << std::endl; + for (int i = 1; i <= n; i++) { + std::clog << dp[1][i] << ' '; + } + std::clog << std::endl; +} + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + + init_dp(); + int n; + std::cin >> n; + std::cout << dp[0][n] % MOD << std::endl;; + log_dp(n); + + return 0; +} diff --git a/cs101/2025mid/exam_2025mid_09_bigfloat.cpp b/cs101/2025mid/exam_2025mid_09_bigfloat.cpp new file mode 100644 index 0000000..d6d40da --- /dev/null +++ b/cs101/2025mid/exam_2025mid_09_bigfloat.cpp @@ -0,0 +1,160 @@ +#include +#include +#include +#include + +constexpr int char_to_digit(char c) { + if (c >= '0' && c <= '9') { return static_cast(c - '0'); } + if (c >= 'A' && c <= 'Z') { return static_cast(c - 'A' + 10); } + throw std::invalid_argument("Invalid char as digit"); +} + +constexpr char digit_to_char(int digit) { + if (digit >= 0 && digit <= 9) { return static_cast('0' + digit); } + return static_cast('A' + digit - 10); +} + +class BigFloat { +public: + std::array, 2> digit_vectors; + bool negative = false; + unsigned short base = 10; + + explicit BigFloat(std::string s, unsigned short base = 10) : base(base) { + int i = 0; + if (s[0] == '-') { negative = true, i++; } + for (; i < s.size() && s[i] != '.'; i++) { digit_vectors[0].push_back(char_to_digit(s[i])); } + std::reverse(digit_vectors[0].begin(), digit_vectors[0].end()); + i++; + for (; i < s.size(); i++) { digit_vectors[1].push_back(char_to_digit(s[i])); } + } + + void normalize() { + digit_vectors[0].push_back(0); + digit_vectors[1].push_back(0); + for (int i = static_cast(digit_vectors[1].size() - 2); i >= 0; i--) { + if (digit_vectors[1][i + 1] >= base) { + digit_vectors[1][i] += digit_vectors[1][i + 1] / base; + digit_vectors[1][i + 1] %= base; + } + if (digit_vectors[1][i + 1] < 0) { + int borrowed = -(digit_vectors[1][i + 1] + 1) / base + 1; + digit_vectors[1][i] -= borrowed; + digit_vectors[1][i + 1] += base * borrowed; + } + } + if (digit_vectors[1][0] >= base) { + digit_vectors[0][0] += digit_vectors[1][0] / base; + digit_vectors[1][0] %= base; + } + if (digit_vectors[1][0] < 0) { + int borrowed = -(digit_vectors[1][0] + 1) / base + 1; + digit_vectors[0][0] -= borrowed; + digit_vectors[1][0] += base * borrowed; + } + for (int i = 1; i < digit_vectors[0].size(); i++) { + if (digit_vectors[0][i - 1] >= base) { + digit_vectors[0][i] += digit_vectors[0][i - 1] / base; + digit_vectors[0][i - 1] %= base; + } + if (digit_vectors[0][i - 1] < 0) { + int borrowed = -(digit_vectors[0][i - 1] + 1) / base + 1; + digit_vectors[0][i] -= borrowed; + digit_vectors[0][i - 1] += base * borrowed; + } + } + + if (digit_vectors[0][digit_vectors[0].size() - 1] < 0) { + // digit_vectors[0][digit_vectors[0].size() - 1] = -digit_vectors[0][digit_vectors[0].size() - 1]; + negative = !negative; + for (auto& digits : digit_vectors) { + for (auto& digit : digits) { digit = -digit; } + } + normalize(); + } + + for (auto& digits : digit_vectors) { + while (!digits.empty() && digits.back() == 0) { digits.pop_back(); } + } + if (digit_vectors[0].size() + digit_vectors[1].size() == 0) { + digit_vectors[0].push_back(0); + negative = false; + } + } + + std::string to_string() { + normalize(); + std::string s; + for (auto digit : digit_vectors[0]) { s += digit_to_char(digit); } + if (negative) { s += '-'; } + std::reverse(s.begin(), s.end()); + if (digit_vectors[1].empty()) { return s; } + s += '.'; + for (auto digit : digit_vectors[1]) { s += digit_to_char(digit); } + return s; + } + + friend std::ostream& operator<<(std::ostream& os, BigFloat big_float) { + return os << big_float.to_string(); + } + + static void align(BigFloat& a, BigFloat& b) { + for (auto part : {0, 1}) { + if (a.digit_vectors[part].size() < b.digit_vectors[part].size()) { + a.digit_vectors[part].resize(b.digit_vectors[part].size()); + } else if (b.digit_vectors[part].size() < a.digit_vectors[part].size()) { + b.digit_vectors[part].resize(a.digit_vectors[part].size()); + } + } + } + + BigFloat operator-() const { + BigFloat result = *this; + result.negative = !result.negative; + return result; + } + + BigFloat& operator+=(BigFloat other) { + if ((negative && !other.negative) || (!negative && other.negative)) { return *this -= -other; } + align(*this, other); + for (auto part : {0, 1}) { + for (int i = 0; i < digit_vectors[part].size(); i++) { + digit_vectors[part][i] += other.digit_vectors[part][i]; + } + } + normalize(); + return *this; + } + + BigFloat& operator-=(BigFloat other) { + if ((negative && !other.negative) || (!negative && other.negative)) { return *this += -other; } + align(*this, other); + for (auto part : {0, 1}) { + for (int i = 0; i < digit_vectors[part].size(); i++) { + digit_vectors[part][i] -= other.digit_vectors[part][i]; + } + } + normalize(); + return *this; + } +}; + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + + int cases; + std::cin >> cases; + while (cases--) { + unsigned short base; + std::string s1, s2; + std::cin >> base >> s1 >> s2; + + BigFloat number1(s1, base), number2(s2, base); + std::clog << number1 << ' ' << number2 << std::endl; + number1 -= number2; + std::cout << number1 << std::endl; + } + + return 0; +} diff --git a/cs101/stage_3/dh_31_01_teeth_dp.cpp b/cs101/stage_3/dh_31_01_teeth_dp.cpp new file mode 100644 index 0000000..71ff822 --- /dev/null +++ b/cs101/stage_3/dh_31_01_teeth_dp.cpp @@ -0,0 +1,26 @@ +#include + +constexpr int MAX_N = 31; + +int dp[MAX_N]; + +void init_dp() { + dp[0] = 1; + dp[1] = 1; + for (int i = 2; i < MAX_N; i++) { + dp[i] = dp[i - 1] + dp[i - 2]; + } +} + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + + init_dp(); + + int n; + std::cin >> n; + std::cout << dp[n] << std::endl; + + return 0; +} diff --git a/cs101/stage_3/dh_31_02_lcm.cpp b/cs101/stage_3/dh_31_02_lcm.cpp new file mode 100644 index 0000000..3d55442 --- /dev/null +++ b/cs101/stage_3/dh_31_02_lcm.cpp @@ -0,0 +1,25 @@ +#include + +long long gcd(long long a, long long b) { + if (a < b) { return gcd(b, a); } + if (b == 1) { return 1; } + if (b == 0) { return a; } + return gcd(b, a % b); +} + +long long lcm(long long a, long long b) { + return a / gcd(a, b) * b; +} + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + + char temp_comma; + long long a, b; + std::cin >> a >> temp_comma >> b; + std::clog << gcd(a, b) << std::endl; + std::cout << lcm(a, b) << std::endl; + + return 0; +} diff --git a/cs101/stage_3/dh_31_03_is_palindromic.cpp b/cs101/stage_3/dh_31_03_is_palindromic.cpp new file mode 100644 index 0000000..a80c6b9 --- /dev/null +++ b/cs101/stage_3/dh_31_03_is_palindromic.cpp @@ -0,0 +1,20 @@ +#include + +bool is_palindromic(std::string s) { + if (s.size() == 1) { return true; } + for (int i = 0; i <= (s.size() - 2) / 2; i++) { + if (s[i] != s[s.size() - i - 1]) { return false; } + } + return true; +} + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + + std::string s; + std::cin >> s; + std::cout << (is_palindromic(s) ? "yes" : "no") << std::endl; + + return 0; +} diff --git a/cs101/stage_3/dh_31_04_kakutani_guess.cpp b/cs101/stage_3/dh_31_04_kakutani_guess.cpp new file mode 100644 index 0000000..cce629c --- /dev/null +++ b/cs101/stage_3/dh_31_04_kakutani_guess.cpp @@ -0,0 +1,22 @@ +#include + +void print_kakutani_process(int n) { + while (n != 1) { + if (n % 2 == 0) { + std::cout << n << "/2=" << (n /= 2) << std::endl; + } else { + std::cout << n << "*3+1=" << (n *= 3, n += 1) << std::endl; + } + } +} + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + + int n; + std::cin >> n; + print_kakutani_process(n); + + return 0; +} diff --git a/cs101/stage_3/dh_31_05_sunwukong.cpp b/cs101/stage_3/dh_31_05_sunwukong.cpp new file mode 100644 index 0000000..3fd6d16 --- /dev/null +++ b/cs101/stage_3/dh_31_05_sunwukong.cpp @@ -0,0 +1,89 @@ +#include +#include +#include + +using Grid = std::vector>; + +class Vector2 { +public: + int x, y; + constexpr explicit Vector2(const int x = 0, const int y = 0) : x(x), y(y) {} + constexpr bool operator==(const Vector2 other) const { return x == other.x && y == other.y; } + constexpr Vector2 operator+(const Vector2 other) const { return Vector2(x + other.x, y + other.y); } +}; + +constexpr Vector2 DIRS[4] = {Vector2(0, 1), Vector2(1, 0), Vector2(0, -1), Vector2(-1, 0)}; + +template +std::ostream& operator<<(std::ostream& os, const std::vector& vector) { + for (auto elem : vector) { os << elem << ' '; } + return os; +} + +template +void log_grid(const std::vector>& grid, const std::string& prefix = "") { + for (auto line : grid) { + std::clog << prefix << ' ' << line << std::endl; + } +} + +Grid get_init_grid(int r, int c) { + Grid grid = std::vector(r + 2, std::vector(c + 2, 0)); + std::fill(grid[0].begin(), grid[0].end(), 1); + std::fill(grid[grid.size() - 1].begin(), grid[grid.size() - 1].end(), 1); + for (int j = 1; j <= r; j++) { + grid[j][0] = grid[j][c + 1] = 1; + } + return grid; +} + +Grid input_grid() { + int r, c; + std::cin >> r >> c; + Grid grid = get_init_grid(r, c); + for (int i = 1; i <= r; i++) { + for (int j = 1; j <= c; j++) { + std::cin >> grid[i][j]; + } + } + return grid; +} + +bool verify_reachability(const Grid& grid, + const Vector2 end_pos, + Vector2 pos, + std::vector>& visited) { + if (pos == end_pos) { return true; } + if (grid[pos.x][pos.y] == 1) { return false; } + if (visited[pos.x][pos.y]) { return false; } + visited[pos.x][pos.y] = true; + // log_grid(visited); + for (const auto dir : DIRS) { + if (verify_reachability(grid, end_pos, pos + dir, visited)) { return true; } + } + return false; +} + + +bool verify_reachability(const Grid& grid) { + Vector2 start_pos, end_pos; + for (int i = 0; i < grid.size(); i++) { + for (int j = 0; j < grid[0].size(); j++) { + if (grid[i][j] == 2) { start_pos = Vector2(i, j); } + if (grid[i][j] == 3) { end_pos = Vector2(i, j); } + } + } + + std::vector visited(grid.size(), std::vector(grid[0].size(), false)); + return verify_reachability(grid, end_pos, start_pos, visited); +} + + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + + std::cout << (verify_reachability(input_grid()) ? "Yes" : "No") << std::endl; + + return 0; +} diff --git a/cs101/stage_3/dh_31_06_legendre_polynomials_dp.cpp b/cs101/stage_3/dh_31_06_legendre_polynomials_dp.cpp new file mode 100644 index 0000000..bcb73d0 --- /dev/null +++ b/cs101/stage_3/dh_31_06_legendre_polynomials_dp.cpp @@ -0,0 +1,24 @@ +#include + +constexpr int MAX_N = 1e6; + +double dp[MAX_N + 1]; + +void init_dp(int x) { + dp[0] = 1, dp[1] = x; + for (int i = 2; i < MAX_N; i++) { + dp[i] = ((2 * i - 1) * x * dp[i - 1] - (i - 1) * dp[i - 2]) / i; + } +} + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + + int n, x; + std::cin >> n >> x; + init_dp(x); + std::cout << dp[n] << std::endl; + + return 0; +} diff --git a/dsa/ch3_stack_queue/template_queue_linear.cpp b/dsa/ch3_stack_queue/template_queue_linear.cpp new file mode 100644 index 0000000..93ecb1b --- /dev/null +++ b/dsa/ch3_stack_queue/template_queue_linear.cpp @@ -0,0 +1,15 @@ +#include + +constexpr std::size_t MAX_SIZE = 10001; + +template +class Queue { + T data[MAX_SIZE]; +}; + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + + return 0; +} diff --git a/dsa/ch4_string/luogu_template_kmp_P3375.cpp b/dsa/ch4_string/template_kmp_elegent.cpp similarity index 90% rename from dsa/ch4_string/luogu_template_kmp_P3375.cpp rename to dsa/ch4_string/template_kmp_elegent.cpp index 4c9e2ca..7aae9bf 100644 --- a/dsa/ch4_string/luogu_template_kmp_P3375.cpp +++ b/dsa/ch4_string/template_kmp_elegent.cpp @@ -38,10 +38,7 @@ int main() { std::string target, pattern; std::cin >> target >> pattern; for (const auto i : find_substring_pos(target, pattern)) { - std::cout << i + 1 << std::endl; - } - for (const auto val : prefix_function(pattern)) { - std::cout << val << " "; + std::cout << i << " "; } std::cout << std::endl; diff --git a/dsa/ch4_string/template_kmp_standard_next.cpp b/dsa/ch4_string/template_kmp_standard_next.cpp new file mode 100644 index 0000000..d1bfa96 --- /dev/null +++ b/dsa/ch4_string/template_kmp_standard_next.cpp @@ -0,0 +1,74 @@ +#include +#include + +std::vector get_next_vector(const std::string& s) { + std::vector next(s.size() + 1); + next[0] = -1; + for (int i = 0; i < next.size() - 1; i++) { // 实际上写入下一位 + int j = next[i]; + while (j != -1 && s[i] != s[j]) { // j = -1: 完全不匹配,s[i]==s[j]: 直接能用 + j = next[j]; + } + if (j == -1 || s[i] == s[j]) { j++; } + next[i + 1] = j; + } + return next; +} + +std::vector get_optimized_next_vector(const std::string& s, const std::vector& next) { + std::vector next_optimized(next.size()); + next_optimized[0] = -1; + next_optimized[next.size() - 1] = next[next.size() - 1]; + for (int i = 1; i < next.size() - 1; i++) { + if (s[next[i]] == s[i]) { + next_optimized[i] = next_optimized[next[i]]; + } else { + next_optimized[i] = next[i]; + } + } + return next_optimized; +} + +std::vector find_substring_pos(const std::string& target, const std::string& pattern) { + std::vector matched_pos; + const std::vector next_vector = get_optimized_next_vector(pattern, get_next_vector(pattern)); + int j = 0; + for (int i = 0; i < target.size(); i++) { + while (j > -1 && target[i] != pattern[j]) { + j = next_vector[j]; + } + if (j == -1) { + j = 0; // 完全失配,直接 i++ j++ + continue; + } + if (target[i] == pattern[j]) { j++; } + if (j == pattern.size()) { + matched_pos.push_back(i - static_cast(pattern.size()) + 1); + j = next_vector[j]; + } + } + return matched_pos; +} + +std::ostream& operator<<(std::ostream& os, std::vector vec) { + for (const auto& elem : vec) { + os << elem << " "; + } + return os; +} + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + + std::string target, pattern; + std::cin >> target >> pattern; + std::clog << get_next_vector(pattern) << std::endl; + std::clog << get_optimized_next_vector(pattern, get_next_vector(pattern)) << std::endl; + for (const auto i : find_substring_pos(target, pattern)) { + std::cout << i << " "; + } + std::cout << std::endl; + + return 0; +} diff --git a/dsa/ch5_binary_tree/dsa_0509_expression_tree.cpp b/dsa/ch5_binary_tree/dsa_0509_expression_tree.cpp new file mode 100644 index 0000000..3d54b30 --- /dev/null +++ b/dsa/ch5_binary_tree/dsa_0509_expression_tree.cpp @@ -0,0 +1,224 @@ +#include +#include +#include +#include +#include +#include + +using Expression = std::string; // 没有数字 + +bool is_operator(const char c) { + return c == '+' || c == '-' || c == '*' || c == '/' + || c == '(' || c == ')'; +} + +int get_priority(char c) { + assert(is_operator(c)); + if (c == '+' || c == '-') { return 1; } + if (c == '*' || c == '/') { return 2; } + throw std::invalid_argument("Invalid operator!"); +} + +class ExpressionTree { +public: + struct Node { + char value; + int depth = -1; + Node *father = nullptr, *left = nullptr, *right = nullptr; + + explicit Node(char c) : value(c) {} + + [[nodiscard]] bool is_operator() const { + return ::is_operator(value); + } + + [[nodiscard]] int get_priority() const { + return ::get_priority(value); + } + }; + + Node* root = nullptr; + int depth = -1; + + void init_depths() { + dfs([this](Node* node, int dfs_depth) { + node->depth = dfs_depth; + depth = std::max(depth, dfs_depth); + }); + depth++; + } + + void init_with_infix(const Expression& expression) { + std::stack ops; + std::stack nums; + + for (char c : expression) { + if (!is_operator(c)) { + nums.push(new Node(c)); + continue; + } + if (c == '(') { + ops.push(new Node(c)); + continue; + } + if (c == ')') { + while (ops.top()->value != '(') { + construct_one_op(ops, nums); + } + ops.pop(); + continue; + } + Node* node = new Node(c); + while (!ops.empty() && ops.top()->value != '(' + && node->get_priority() <= ops.top()->get_priority()) { + construct_one_op(ops, nums); + } + ops.push(node); + } + while (!ops.empty()) { + construct_one_op(ops, nums); + } + root = nums.top(); + init_depths(); + } + +protected: + static void construct_one_op(std::stack& ops, std::stack& nums) { + auto op = ops.top(); + ops.pop(); + auto num_right = nums.top(); + nums.pop(); + auto num_left = nums.top(); + nums.pop(); + op->left = num_left; + op->right = num_right; + num_left->father = op; + num_right->father = op; + nums.push(op); + } + +public: + [[nodiscard]] Expression get_postfix() const { + Expression expression; + // 此代码正确,但是本人想试试 dfs + // std::stack> stack; // 0: 没干过活,1: 玩过左,2: 玩过右 + // stack.emplace(root, 0); + // while (!stack.empty()) { + // // std::clog << "Top: " << stack.top().first->value << ", flag=" << stack.top().second << std::endl; + // if (stack.top().second == 0) { + // stack.top().second++; + // if (stack.top().first->left != nullptr) { + // stack.emplace(stack.top().first->left, 0); + // } + // } else if (stack.top().second == 1) { + // stack.top().second++; + // if (stack.top().first->right != nullptr) { + // stack.emplace(stack.top().first->right, 0); + // } + // } else { + // expression += stack.top().first->value; + // stack.pop(); + // } + // } + dfs([&expression](Node* node, int _) { + expression.push_back(node->value); + }, 2); + return expression; + + } + + std::vector get_string_lines() { + std::vector lines(depth * 2); + dfs_with_id([&lines](Node* node, unsigned long long node_id) { + lines[node->depth * 2].resize(node_id, ' '); + lines[node->depth * 2][node_id - 1] = node->value; + if (node->left != nullptr) { + lines[node->depth * 2 + 1].resize(node_id - 1, ' '); + lines[node->depth * 2 + 1][node_id - 2] = '/'; + } + if (node->right != nullptr) { + lines[node->depth * 2 + 1].resize(node_id + 1, ' '); + lines[node->depth * 2 + 1][node_id] = '\\'; + } + }, 2); + lines.pop_back(); + return lines; + } + + long long calculate(const std::unordered_map& variable_map, Node* node = nullptr) { + if (node == nullptr) { node = root; } + if (node->left == nullptr) { return variable_map.at(node->value); } + long long left = calculate(variable_map, node->left); + long long right = calculate(variable_map, node->right); + if (node->value == '+') { return left + right; } + if (node->value == '-') { return left - right; } + if (node->value == '*') { return left * right; } + if (node->value == '/') { return left / right; } + throw std::logic_error(""); + } + +protected: + void dfs(const std::function& func, + int func_entry = 0, + int dfs_depth = 0, + Node* node = nullptr) const { + if (dfs_depth == 0) { node = root; } + if (func_entry == 0) { func(node, dfs_depth); } + if (node->left != nullptr) { dfs(func, func_entry, dfs_depth + 1, node->left); } + if (func_entry == 1) { func(node, dfs_depth); } + if (node->right != nullptr) { dfs(func, func_entry, dfs_depth + 1, node->right); } + if (func_entry == 2) { func(node, dfs_depth); } + } + + void dfs_with_id(const std::function& func, + int func_entry = 0, + unsigned long long node_id = 0, + Node* node = nullptr) const { + if (node == nullptr) { node = root, node_id = 1 << (depth - 1); } + // std::clog << node_id << std::endl; + unsigned long long depth_bit = 1ull << (depth - node->depth - 1); + unsigned long long flipped_depth_bit = ~0ull ^ depth_bit; + if (func_entry == 0) { func(node, node_id); } + if (node->left != nullptr) { + dfs_with_id(func, func_entry, (node_id & flipped_depth_bit) | (depth_bit >> 1), node->left); + } + if (func_entry == 1) { func(node, node_id); } + if (node->right != nullptr) { + dfs_with_id(func, func_entry, node_id | (depth_bit >> 1), node->right); + } + if (func_entry == 2) { func(node, node_id); } + } + + friend std::ostream& operator<<(std::ostream& os, ExpressionTree expression_tree) { + for (const auto& line : expression_tree.get_string_lines()) { + os << line << std::endl; + } + return os; + } +}; + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + + Expression infix_expression; + std::cin >> infix_expression; + + ExpressionTree expression_tree; + expression_tree.init_with_infix(infix_expression); + std::cout << expression_tree.get_postfix() << std::endl; + std::cout << expression_tree; + + int n; + std::cin >> n; + std::unordered_map variable_map; + for (int i = 0; i < n; i++) { + char c; + int x; + std::cin >> c >> x; + variable_map[c] = x; + } + std::cout << expression_tree.calculate(variable_map) << std::endl; + + return 0; +} diff --git a/dsa/ch5_binary_tree/dsa_0512_text_binary_tree.cpp b/dsa/ch5_binary_tree/dsa_0512_text_binary_tree.cpp new file mode 100644 index 0000000..3fb9b24 --- /dev/null +++ b/dsa/ch5_binary_tree/dsa_0512_text_binary_tree.cpp @@ -0,0 +1,107 @@ +#include +#include +#include + +class BinaryTree { +public: + using NodeIdx = int; + + struct Node { + char value; + NodeIdx left = -1, right = -1; + }; + + enum class FuncEntry { Pre, In, Post }; + + NodeIdx root = -1; + std::vector nodes; + + void init_with_lines(const std::vector& lines) { + nodes.reserve(lines.size()); + std::vector lines_dashes(lines.size()); + int idx = 0; + root = init_with_lines(lines, 0, idx); + } + + std::string prefix_traverse() { + std::string traverse; + traverse.reserve(nodes.size()); + dfs([&traverse, this](NodeIdx node, int dfs_depth) { + traverse += nodes[node].value; + }, FuncEntry::Pre); + return traverse; + } + + std::string infix_traverse() { + std::string traverse; + traverse.reserve(nodes.size()); + dfs([&traverse, this](NodeIdx node, int dfs_depth) { + traverse += nodes[node].value; + }, FuncEntry::In); + return traverse; + } + + std::string postfix_traverse() { + std::string traverse; + traverse.reserve(nodes.size()); + dfs([&traverse, this](NodeIdx node, int dfs_depth) { + traverse += nodes[node].value; + }, FuncEntry::Post); + return traverse; + } + +protected: + NodeIdx init_with_lines(const std::vector& lines, + int depth, int& idx) { + if (idx >= lines.size() || lines[idx].size() - 1 < depth) { return -1; } + char value; + if ((value = lines[idx][lines[idx].size() - 1]) == '*') { + idx++; + return -1; + } + const NodeIdx node_idx = nodes.size(); + nodes.push_back(Node{value}); + idx++; + nodes[node_idx].left = init_with_lines(lines, depth + 1, idx); + nodes[node_idx].right = init_with_lines(lines, depth + 1, idx); + return node_idx; + } + + void dfs(const std::function& func, + FuncEntry func_entry = FuncEntry::Pre, + int dfs_depth = 0, + NodeIdx node = -1 + ) { + if (dfs_depth == 0) { node = root; } + if (func_entry == FuncEntry::Pre) { func(node, dfs_depth); } + if (nodes[node].left != -1) { dfs(func, func_entry, dfs_depth + 1, nodes[node].left); } + if (func_entry == FuncEntry::In) { func(node, dfs_depth); } + if (nodes[node].right != -1) { dfs(func, func_entry, dfs_depth + 1, nodes[node].right); } + if (func_entry == FuncEntry::Post) { func(node, dfs_depth); } + } +}; + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + + int n; + std::cin >> n; + + while (n--) { + std::vector lines; + std::string s; + while (std::cin >> s && s != "0") { + lines.push_back(s); + } + + BinaryTree binary_tree; + binary_tree.init_with_lines(lines); + + std::cout << binary_tree.prefix_traverse() << std::endl + << binary_tree.postfix_traverse() << std::endl + << binary_tree.infix_traverse() << std::endl << std::endl; + } + + return 0; +} diff --git a/dsa/ch5_binary_tree/luogu_template_huffman_B2168.cpp b/dsa/ch5_binary_tree/luogu_template_huffman_B2168.cpp new file mode 100644 index 0000000..d8f4291 --- /dev/null +++ b/dsa/ch5_binary_tree/luogu_template_huffman_B2168.cpp @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include +#include + +class HuffmanTree { +public: + struct Node { + long long weight; + std::optional content; + Node *left = nullptr, *right = nullptr; + + bool operator<(const Node& other) const { + return weight < other.weight; + } + }; + + enum class DfsEntries { Pre, In, Post }; + + Node* root = nullptr; + + explicit HuffmanTree(const std::unordered_map& freq_map) { + std::priority_queue, + std::function> + nodes_heap([](Node* a, Node* b) { return a->weight > b->weight; }); + for (const auto& [key, freq] : freq_map) { + nodes_heap.push(new Node{.weight = freq, .content = key}); + } + while (nodes_heap.size() > 1) { + Node* node1 = nodes_heap.top(); + nodes_heap.pop(); + Node* node2 = nodes_heap.top(); + nodes_heap.pop(); + Node* new_node = new Node{.weight = node1->weight + node2->weight, .left = node1, .right = node2}; + nodes_heap.push(new_node); + } + root = nodes_heap.top(); + } + + std::unordered_map> get_encodings() { + std::unordered_map> encodings; + if (root->left == nullptr && root->right == nullptr) { + encodings[root->content.value()] = {false}; + } else { + dfs_with_path([&encodings](Node* node, std::vector path) { + if (!node->content.has_value()) { return; } + encodings[node->content.value()] = std::move(path); + }); + } + return encodings; + } + +protected: + void dfs_with_path(const std::function)>& func, + DfsEntries func_entry = DfsEntries::Pre) { + std::vector path; + dfs_with_path(func, func_entry, path); + } + + void dfs_with_path(const std::function)>& func, + DfsEntries func_entry, + std::vector& path, + Node* node = nullptr) { + if (node == nullptr) { node = root; } + if (func_entry == DfsEntries::Pre) { func(node, path); } + if (node->left != nullptr) { + path.push_back(false); + dfs_with_path(func, func_entry, path, node->left); + path.pop_back(); + } + if (func_entry == DfsEntries::In) { func(node, path); } + if (node->right != nullptr) { + path.push_back(true); + dfs_with_path(func, func_entry, path, node->right); + path.pop_back(); + } + if (func_entry == DfsEntries::Post) { func(node, path); } + } +}; + +std::ostream& operator<<(std::ostream& os, const std::vector& bintree_path) { + for (const auto bin : bintree_path) { + os << (bin ? 1 : 0); + } + return os; +} + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + + int n; + std::cin >> n; + + std::vector keys(n); + std::unordered_map freq_map; + for (int i = 0; i < n; i++) { + int freq; + std::cin >> keys[i] >> freq; + freq_map[keys[i]] = freq; + } + + HuffmanTree huffman_tree(freq_map); + auto encodings = huffman_tree.get_encodings(); + for (const auto& key : keys) { + std::cout << key << ' ' << encodings[key] << std::endl; + } + + return 0; +} diff --git a/dsa/ch6_tree/dsa_0603_crime_gangs.cpp b/dsa/ch6_tree/dsa_0603_crime_gangs.cpp new file mode 100644 index 0000000..3ccc8a0 --- /dev/null +++ b/dsa/ch6_tree/dsa_0603_crime_gangs.cpp @@ -0,0 +1,88 @@ +#include +#include + +/** + * 带权并查集。权重记录该节点到父节点的边的边权(保证一切根节点权重为 0) + */ +class DsuWeighted { +public: + using NodeIdx = int; + + struct Node { + NodeIdx parent = -1; + int weight = 0; + std::size_t size = 1; + }; + + std::vector nodes; + const int groups_amount; + + explicit DsuWeighted(const std::size_t n, int groups = 2) : nodes(n), groups_amount(groups) { + for (auto i = 0; i < n; i++) { + nodes[i].parent = i; + } + } + + NodeIdx find(const NodeIdx x) { + if (nodes[x].parent == x) { return x; } + find(nodes[x].parent); + nodes[x].weight += nodes[nodes[x].parent].weight; + nodes[x].weight %= groups_amount; + return nodes[x].parent = find(nodes[x].parent); + } + + int get_weight(const NodeIdx x) { + find(x); + return nodes[x].weight; + } + + void unite(NodeIdx x, NodeIdx y, int weight_delta = 0) { + auto x_root = find(x), y_root = find(y); + if (x_root == y_root) { return; } + if (nodes[x_root].size > nodes[y_root].size) { + std::swap(x, y); + std::swap(x_root, y_root); + weight_delta = -weight_delta; + } + nodes[x_root].weight += weight_delta + nodes[y].weight - nodes[x].weight; + nodes[x_root].weight %= groups_amount; + nodes[x_root].parent = y_root; + nodes[y_root].size += nodes[x_root].size; + } +}; + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + std::cout.tie(nullptr); + + int test_cases_amount; + std::cin >> test_cases_amount; + while (test_cases_amount--) { + int cases_amount, queries_amount; + std::cin >> cases_amount >> queries_amount; + + DsuWeighted dsu(cases_amount, 2); + while (queries_amount--) { + char op; + int case_id_1, case_id_2; + std::cin >> op >> case_id_1 >> case_id_2; + case_id_1--, case_id_2--; + if (op == 'D') { + dsu.unite(case_id_1, case_id_2, 1); + } else if (op == 'A') { + if (dsu.find(case_id_1) != dsu.find(case_id_2)) { + std::cout << "Not sure yet." << std::endl; + } else { + if ((dsu.get_weight(case_id_1) - dsu.get_weight(case_id_2)) % 2 == 0) { + std::cout << "In the same gang." << std::endl; + } else { + std::cout << "In different gangs." << std::endl; + } + } + } + } + } + + return 0; +} diff --git a/dsa/ch6_tree/dsa_0613_tree_conversion.cpp b/dsa/ch6_tree/dsa_0613_tree_conversion.cpp new file mode 100644 index 0000000..504255d --- /dev/null +++ b/dsa/ch6_tree/dsa_0613_tree_conversion.cpp @@ -0,0 +1,144 @@ +#include +#include +#include + +using NodeIdx = std::size_t; +static constexpr NodeIdx NULL_IDX = static_cast(-1); + +template +class Tree { +public: + enum class FuncEntry { Pre, Post }; + + struct Node { + T value; + NodeIdx parent = NULL_IDX; + std::vector children; + }; + + std::vector nodes; + NodeIdx root = NULL_IDX; + + NodeIdx add_node(const Node& node_obj) { + nodes.push_back(node_obj); + return nodes.size() - 1; + } + + void init_with_dfs(const std::string& dfs_string) { + root = add_node({.value = T()}); + init_with_dfs(dfs_string, 0, root); + } + + int get_height() { + int depth = -1; + dfs([&depth](NodeIdx node, int dfs_depth) { depth = std::max(depth, dfs_depth); }); + return depth; + } + +protected: + void init_with_dfs(const std::string& dfs_string, std::size_t s_idx, NodeIdx node) { + if (s_idx >= dfs_string.size()) { return; } + if (dfs_string[s_idx] == 'd') { + auto new_node = add_node({.value = T(), .parent = node}); + nodes[node].children.push_back(new_node); + init_with_dfs(dfs_string, s_idx + 1, nodes[node].children.back()); + } else { + init_with_dfs(dfs_string, s_idx + 1, nodes[node].parent); + } + } + + void dfs(const std::function& func, + FuncEntry func_entry = FuncEntry::Post, + int depth = 0, + NodeIdx node = NULL_IDX + ) { + if (depth == 0) { node = root; } + if (func_entry == FuncEntry::Pre) { func(node, depth); } + for (auto child : nodes[node].children) { + dfs(func, func_entry, depth + 1, child); + } + if (func_entry == FuncEntry::Post) { func(node, depth); } + } +}; + +template +class BinaryTree { +public: + enum class FuncEntry { Pre, In, Post }; + + struct Node { + T value; + NodeIdx parent = NULL_IDX, left = NULL_IDX, right = NULL_IDX; + }; + + std::vector nodes; + NodeIdx root = -1; + + NodeIdx add_node(Node node_obj) { + nodes.push_back(node_obj); + return nodes.size() - 1; + } + + void init_from_tree(const Tree& tree) { + root = add_node({}); + init_from_tree(tree, tree.root, 0); + } + + int get_height() { + int depth = -1; + dfs([&depth](NodeIdx node, int dfs_depth) { depth = std::max(depth, dfs_depth); }); + return depth; + } + +protected: + void init_from_tree(const Tree& tree, NodeIdx binary_tree_node, NodeIdx tree_node) { + bool first_child = false; + NodeIdx current_parent = NULL_IDX; + for (auto child : tree.nodes[tree_node].children) { + if (!first_child) { + first_child = true; + NodeIdx new_node = add_node({.value = T(), .parent = binary_tree_node}); + nodes[binary_tree_node].left = new_node; + current_parent = nodes[binary_tree_node].left; + init_from_tree(tree, nodes[binary_tree_node].left, child); + continue; + } + NodeIdx new_node = add_node({.value = T(), .parent = current_parent}); + nodes[current_parent].right = new_node; + current_parent = nodes[current_parent].right; + init_from_tree(tree, current_parent, child); + } + } + + void dfs(const std::function& func, + FuncEntry func_entry = FuncEntry::Pre, + int dfs_depth = 0, + NodeIdx node = -1 + ) { + if (dfs_depth == 0) { node = root; } + if (func_entry == FuncEntry::Pre) { func(node, dfs_depth); } + if (nodes[node].left != -1) { dfs(func, func_entry, dfs_depth + 1, nodes[node].left); } + if (func_entry == FuncEntry::In) { func(node, dfs_depth); } + if (nodes[node].right != -1) { dfs(func, func_entry, dfs_depth + 1, nodes[node].right); } + if (func_entry == FuncEntry::Post) { func(node, dfs_depth); } + } +}; + +struct ManualVoid {}; + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + std::cout.tie(nullptr); + + std::string dfs_string; + for (int i = 0; std::cin >> dfs_string && dfs_string != "#"; i++) { + Tree tree; + tree.init_with_dfs(dfs_string); + BinaryTree binary_tree; + binary_tree.init_from_tree(tree); + std::cout << "Tree " << i + 1 << ": " << tree.get_height() << " => " << binary_tree.get_height() << std::endl; + } + + return 0; +} diff --git a/dsa/ch7_graph/template_adjacent_list.cpp b/dsa/ch7_graph/template_adjacent_list.cpp new file mode 100644 index 0000000..a946712 --- /dev/null +++ b/dsa/ch7_graph/template_adjacent_list.cpp @@ -0,0 +1,64 @@ +#include +#include +#include + +class Graph { +public: + struct EdgeNode { + std::size_t end_vertex; + int weight = 1; + std::unique_ptr next = nullptr; + + EdgeNode(std::size_t end_vertex, int weight, std::unique_ptr&& next = nullptr) { + this->end_vertex = end_vertex; + this->weight = weight; + this->next = std::move(next); + } + }; + + struct VertexNode { + int value = -1; + std::unique_ptr first_edge = nullptr; + }; + + std::vector vertices; + + explicit Graph(int vertices_size) : vertices(vertices_size) {} + + void add_edge(std::size_t start_vertex, std::size_t end_vertex, int weight = 1, const bool two_dirs = false) { + // 效率上考量,向头部加边 + // if (vertices[start_vertex].first_edge == nullptr) { + // vertices[start_vertex].first_edge = std::make_unique(end_vertex, weight); + // } else { + // auto head = std::move(vertices[start_vertex].first_edge); + // vertices[start_vertex].first_edge = std::make_unique(end_vertex, weight); + // vertices[start_vertex].first_edge->next = std::move(head); + // } + vertices[start_vertex].first_edge = std::make_unique( + end_vertex, weight, std::move(vertices[start_vertex].first_edge)); + if (two_dirs) { + add_edge(end_vertex, start_vertex, weight, false); + } + } +}; + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + + int n; + std::cin >> n; + Graph graph(n); + for (int i = 0; i < n - 1; i++) { + char node_c; + int edges_amount; + std::cin >> node_c >> edges_amount; + for (int _ = 0; _ < edges_amount; _++) { + int edge_weight; + std::cin >> node_c >> edge_weight; + graph.add_edge(i, node_c - 'A', edge_weight, true); + } + } + + return 0; +} diff --git a/dsa/ch7_graph/template_chained_forward_stare.cpp b/dsa/ch7_graph/template_chained_forward_stare.cpp new file mode 100644 index 0000000..2bea56f --- /dev/null +++ b/dsa/ch7_graph/template_chained_forward_stare.cpp @@ -0,0 +1,8 @@ +#include + +int main() { + std::ios::sync_with_stdio(false); + std::cin.tie(nullptr); + + return 0; +} diff --git a/pojcs101_T04117_split_int.cpp b/pojcs101_T04117_split_int.cpp index 7a2d246..185f8dd 100644 --- a/pojcs101_T04117_split_int.cpp +++ b/pojcs101_T04117_split_int.cpp @@ -3,18 +3,19 @@ using namespace std; -constexpr int MAX_N = 100; -int cache[MAX_N * MAX_N]; +constexpr int MAX_N = 5001, MOD = 1e9 + 7; +long long cache[MAX_N * MAX_N + MAX_N]; -int get_split_solutions_count(int n, int parts_count) { +long long get_split_solutions_count(int n, int parts_count) { if (n <= 0 || parts_count > n) { return 0; } if (parts_count == 1 || parts_count == n) { return 1; } if (cache[n * MAX_N + parts_count] != 0) { return cache[n * MAX_N + parts_count]; } - int ans = 0; + long long ans = 0; for (int i = 1; i <= n / 2; i++) { ans += get_split_solutions_count(n - i - (i - 1) * (parts_count - 1), parts_count - 1); + ans %= MOD; } cache[n * MAX_N + parts_count] = ans; return ans; @@ -27,9 +28,10 @@ int main() { int n; while (cin >> n) { // cout << get_split_solutions_count(n, 2) << endl; - int ans = 0; + long long ans = 0; for (int i = 1; i <= n; i++) { ans += get_split_solutions_count(n, i); + ans %= MOD; // clog << i << ":" << ans << " "; } cout << ans << endl;