[{"content":"","date":"Sep 14, 2026","externalUrl":null,"permalink":"/en/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"","date":"Sep 14, 2026","externalUrl":null,"permalink":"/en/tags/codex/","section":"Tags","summary":"","title":"Codex","type":"tags"},{"content":"Welcome to Dawn Magnet\u0026rsquo;s technical notebook. Browse the English translations below, or switch to Simplified Chinese to read the original articles.\n","date":"Sep 14, 2026","externalUrl":null,"permalink":"/en/","section":"Dawn Magnet's Site","summary":"","title":"Dawn Magnet's Site","type":"page"},{"content":"Installing Codex on Windows without administrator rights can fail before the download even begins. OpenAI\u0026rsquo;s Windows documentation gives a short installation command.\nwinget install --id 9PLM9XGG6VKS -s msstore Use that command when it works. Some managed computers do not have a usable winget, and the msstore source may be unavailable. The user can see Codex in Microsoft Store but cannot repair App Installer or change machine-wide policy.\nI wrote wingets to cover this narrow case. It uses the Codex Store product ID to find the official packages, downloads them into the user\u0026rsquo;s profile, and registers them for the current user with Add-AppxPackage. It needs no administrator rights and installs no PowerShell module.\nInstall Codex first # Open DawnMagnet\u0026rsquo;s wingets Gist if you want to inspect the complete source before running it. The following commands save the script under the current user\u0026rsquo;s LocalAppData and do not write to a system directory.\n$wingetsPath = Join-Path $env:LOCALAPPDATA \u0026#39;wingets\\wingets.ps1\u0026#39; $wingetsDir = Split-Path $wingetsPath New-Item -ItemType Directory -Force -Path $wingetsDir | Out-Null Invoke-WebRequest ` -Uri \u0026#39;https://gist.githubusercontent.com/DawnMagnet/3b05c689a849ba0cfc48cbaf55969d32/raw/wingets.ps1\u0026#39; ` -OutFile $wingetsPath Then install Codex.\npowershell.exe -NoProfile -ExecutionPolicy Bypass ` -File $wingetsPath install 9PLM9XGG6VKS -ExecutionPolicy Bypass applies only to the PowerShell process started by this command. It does not persistently change the machine or current-user execution policy. The script selects x64 by default. Windows on Arm devices should request arm64 explicitly.\npowershell.exe -NoProfile -ExecutionPolicy Bypass ` -File $wingetsPath install 9PLM9XGG6VKS --architecture arm64 Downloads go to %USERPROFILE%\\Downloads\\wingets by default. You can remove the script and download directory after installation without affecting the registered Codex app. Do not add --force for a first installation. That option removes the existing current-user package first and may also remove application data or settings.\nThe gap Wingets covers # The official command depends on Windows Package Manager, the msstore source, and a working App Installer registration on the computer. An administrator can repair or redeploy those components. A regular user often has to stop there.\nwingets skips an unavailable or damaged winget client while continuing to use Microsoft services and Windows package registration. It does not elevate privileges or evade organization policy. That distinction matters.\nThe script follows a compact path.\nCodex Store product ID 9PLM9XGG6VKS │ ▼ Microsoft Store catalog returns WuCategoryId │ ▼ Windows Update resolves current Retail packages and dependencies │ ▼ Microsoft CDN download with digest verification │ ▼ Add-AppxPackage registers packages for the current user Microsoft Store product metadata provides PackageFamilyName and WuCategoryId. The first value checks whether Codex is already installed. The second lets Windows Update resolve the current MSIX, AppX, and dependency packages. The script joins metadata and download URLs by FileDigest instead of assuming that response lists always use the same order.\nDownloads are restricted to *.delivery.mp.microsoft.com. After each file is written, the script checks the SHA-1 digest returned by Windows Update over HTTPS. Windows then validates package signatures during installation. SHA-1 verifies the transferred bytes here, while publisher trust remains the job of Windows signature validation.\nWhy WinStoreRip was removed # The early version depended on WinStoreRip. Further inspection showed that the target computer also needed PowerShell Gallery access and that package-link discovery depended on a third-party web page. Restricted computers are already prone to network and component failures, so installing another module at runtime added avoidable failure points.\nThe current wingets.ps1 is a single file. It talks directly to Microsoft Store, Windows Update, and Microsoft CDN. It does not need WinStoreRip or a third-party package-link service.\nNo administrator rights still has limits # Wingets registers Store packages only for the current user and does not support --scope machine. If an organization explicitly blocks the package through AppLocker, WDAC, or AppX policy, the script will fail. It does not bypass those controls.\nThe computer must reach storeedgefd.dsx.mp.microsoft.com, fe3.delivery.mp.microsoft.com, and *.delivery.mp.microsoft.com. GitHub is needed only to obtain the script. If the Gist is inaccessible, download wingets.ps1 on another computer and copy it over.\nOnly the current Retail channel is supported, and arbitrary historical versions are unavailable. Wingets is not a complete winget replacement. It does not process MSI, EXE, portable, or archive packages from the community repository. Its purpose stays narrow and practical, installing the Microsoft Store release of Codex under regular user permissions.\nWhat I actually tested # The published version completed 26 tests under both Windows PowerShell 5.1 and PowerShell 7. The matrix covers Chinese and English output, short and long options, option ordering, explicit error boundaries, read-only Store lookup, digest metadata, CDN host restrictions, and a one-byte Range request.\nA live query on September 14, 2026 returned OpenAI.Codex 26.908.4834.0 at 774,918,112 bytes. Microsoft CDN answered the Range request with 206 Partial Content. The final validation did not download the complete 739 MiB package again or forcibly uninstall the existing Codex app. Those operations would consume bandwidth or alter the workstation without adding useful coverage.\nIf the official winget command works, Wingets adds no benefit. Its use case is specific. You can run ordinary PowerShell and reach Microsoft\u0026rsquo;s Store and update services, but you do not have administrator rights to repair a broken installation path.\nReferences # OpenAI Windows desktop app documentation GetCookie in the Microsoft Windows Update Services Protocol SyncUpdates in the Microsoft Windows Update Services Protocol Add-AppxPackage on Microsoft Learn PowerShell execution policies on Microsoft Learn ","date":"Sep 14, 2026","externalUrl":null,"permalink":"/en/posts/wingets/","section":"Posts","summary":"","title":"Installing Codex on Windows Without Administrator Rights","type":"posts"},{"content":"","date":"Sep 14, 2026","externalUrl":null,"permalink":"/en/tags/microsoft-store/","section":"Tags","summary":"","title":"Microsoft Store","type":"tags"},{"content":"","date":"Sep 14, 2026","externalUrl":null,"permalink":"/en/posts/","section":"Posts","summary":"","title":"Posts","type":"posts"},{"content":"","date":"Sep 14, 2026","externalUrl":null,"permalink":"/en/tags/powershell/","section":"Tags","summary":"","title":"PowerShell","type":"tags"},{"content":"","date":"Sep 14, 2026","externalUrl":null,"permalink":"/en/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":"","date":"Sep 14, 2026","externalUrl":null,"permalink":"/en/categories/windows/","section":"Categories","summary":"","title":"Windows","type":"categories"},{"content":"","date":"Sep 14, 2026","externalUrl":null,"permalink":"/en/tags/winget/","section":"Tags","summary":"","title":"Winget","type":"tags"},{"content":" Affine Cipher (affine-break) Analysis Tool Explained # Project Information # This article introduces the affine-break tool, a component of the ctf-tools-rs project, a collection of tools optimized for CTF competitions.\nRepository Links # Full project: https://github.com/DawnMagnet/ctf-tools-rs.git\nIncludes multiple CTF-related tools, such as cipher breaking, image steganography, and data extraction A reference for Rust ecosystem best practices Examples of workspace management and cross-platform builds Standalone tool: https://github.com/DawnMagnet/affine-break\nContains only the affine-break source code Suitable for standalone use or further development Has a lighter dependency footprint License # License type: MIT Author: DawnMagnet Current version: 1.5.0 Introduction # In CTF (Capture The Flag) competitions and cryptography research, we often encounter classic ciphers. The Affine Cipher is a simple and elegant encryption method, but it also has obvious security weaknesses. This article explains what an affine cipher is and how to write an efficient affine-cipher cracking tool in Rust.\nWhat Is an Affine Cipher? # Basic Concept # An affine cipher (Affine Cipher) is a monoalphabetic substitution cipher that uses an affine function for encryption.\nEncryption Formula # For the plaintext letter position x (A=0, B=1, \u0026hellip;, Z=25), encryption is performed as follows:\n$$E(x) = (ax + b) \\bmod 26$$where:\na is the multiplication key, which must satisfy \\(\\gcd(a, 26) = 1\\) (it must be coprime with 26) b is the shift key, which can be any integer from 0 to 25 26 is the total number of letters in the English alphabet Decryption Formula # Decryption requires the modular multiplicative inverse \\(a^{-1}\\):\n$$D(y) = a^{-1}(y - b) \\bmod 26$$ Worked Example # Suppose we choose \\(a = 5, b = 8\\):\nThe letter \u0026lsquo;A\u0026rsquo; (0) → \\((5×0 + 8) \\bmod 26 = 8\\) → \u0026lsquo;I\u0026rsquo; The letter \u0026lsquo;B\u0026rsquo; (1) → \\((5×1 + 8) \\bmod 26 = 13\\) → \u0026lsquo;N\u0026rsquo; The letter \u0026lsquo;C\u0026rsquo; (2) → \\((5×2 + 8) \\bmod 26 = 18\\) → \u0026lsquo;S\u0026rsquo; Security Issues of the Affine Cipher # The affine cipher appears to provide two key parameters, but its security is actually far weaker than that of modern ciphers:\nLimited key space:\na has only \\(\\phi(26) = 12\\) valid values (the numbers coprime with 26) b has 26 valid values There are only \\(12 × 26 = 312\\) possible key combinations Vulnerability to known-plaintext attacks: knowing only two plaintext-ciphertext character correspondences is enough to fully recover the key\nFrequency analysis is practical: as a monoalphabetic substitution cipher, it is vulnerable to frequency-analysis attacks\nBecause of these fundamental weaknesses, the affine cipher has practical value mainly for education and CTF competitions.\nIntroducing affine-break # Tool Features # affine-break is a lightweight tool written in Rust that quickly cracks affine ciphers using a known-plaintext attack:\n✅ Only two plaintext-ciphertext character correspondences are needed ✅ Automatically calculate the key parameters a and b ✅ Quickly decrypt an entire ciphertext ✅ Support mixed uppercase and lowercase letters ✅ Preserve non-letter content such as digits, symbols, and spaces Usage # affine-break \u0026lt;密文\u0026gt; \u0026lt;密文字符1\u0026gt; \u0026lt;明文字符1\u0026gt; \u0026lt;密文字符2\u0026gt; \u0026lt;明文字符2\u0026gt; Parameter Description # Parameter Description ciphertext The ciphertext to decrypt ciphertext_char_1 The first known character in the ciphertext plaintext_char_1 The corresponding plaintext character ciphertext_char_2 The second known character in the ciphertext plaintext_char_2 The corresponding plaintext character Usage Example # Suppose we have the ciphertext \u0026quot;prwy{w14wf3p5-fo6w-11gf-w02o-88g9pg5197wo}\u0026quot;.\nWe know that its plaintext should follow a flag format, which usually begins with flag{.\naffine-break \u0026#34;prwy{w14wf3p5-fo6w-11gf-w02o-88g9pg5197wo}\u0026#34; p f r l Explanation:\nThe first ciphertext character \u0026lsquo;p\u0026rsquo; → plaintext character \u0026lsquo;f\u0026rsquo; The second ciphertext character \u0026lsquo;r\u0026rsquo; → plaintext character \u0026rsquo;l\u0026rsquo; Output:\nflag{a14ab3f5-bc6a-11eb-a02c-88e9fe5197ac} Technical Implementation Details # Core Algorithm # The tool\u0026rsquo;s cracking process consists of the following steps:\n1. Character-to-number conversion # const fn char_to_num(c: char) -\u0026gt; i32 { if c.is_ascii_lowercase() { c as i32 - \u0026#39;a\u0026#39; as i32 } else { c as i32 - \u0026#39;A\u0026#39; as i32 } } Convert each letter to its corresponding number (A/a → 0, B/b → 1, \u0026hellip;, Z/z → 25).\n2. Key calculation — solving a linear system # Given two plaintext-ciphertext correspondences: \\((x_1, c_1)\\) and \\((x_2, c_2)\\)\nWe have the following system of equations:\n$$ax_1 + b \\equiv c_1 \\pmod{26}$$ $$ax_2 + b \\equiv c_2 \\pmod{26}$$Subtracting the two equations eliminates b:\n$$a(x_1 - x_2) \\equiv (c_1 - c_2) \\pmod{26}$$const fn solve_a_and_b(c1: char, x1: char, c2: char, x2: char) -\u0026gt; Option\u0026lt;(i32, i32)\u0026gt; { let diff_c = char_to_num(c1) - char_to_num(c2); let diff_x = char_to_num(x1) - char_to_num(x2); let mut a = 0; while a \u0026lt; 26 { if mod_space(diff_x * a) == mod_space(diff_c) { let b = mod_space(char_to_num(c1) - (a * char_to_num(x1))); return Some((a, b)); } a += 1; } None } Algorithm steps:\nBrute-force every possible value of a (0–25) For each a, check whether the equation \\(\\mathrm{diff}_x \\times a \\equiv \\mathrm{diff}_c \\pmod{26}\\) is satisfied Once a suitable a is found, calculate b from the first equation: \\(b = c_1 - ax_1 \\pmod{26}\\) Return the (a, b) pair after successful verification Time complexity: \\(O(1)\\) (at most 26 iterations)\n3. Modular arithmetic helper # const fn mod_space(x: i32) -\u0026gt; i32 { x.rem_euclid(26) } Use rem_euclid rather than % to handle negative numbers and ensure that the result always lies in the range 0–25. This is essential for modular arithmetic.\nWhy this matters:\n% may return a negative number in Rust rem_euclid always returns a non-negative value 4. Decryption # fn affine_decrypt(info: \u0026amp;str, a: i32, b: i32) -\u0026gt; String { let mut inverse_map = [0; 26]; // 构建逆映射表 for i in 0..26 { inverse_map[mod_space(a * i + b) as usize] = i; } let mut result = String::new(); // 遍历每个字符进行解密 for x in info.chars() { if x.is_ascii_alphabetic() { let num = inverse_map[char_to_num(x) as usize]; if x.is_ascii_lowercase() { result.push((b\u0026#39;a\u0026#39; + num as u8) as char); } else { result.push((b\u0026#39;A\u0026#39; + num as u8) as char); } } else { result.push(x); // 保留非字母字符 } } result } Decryption approach:\nBuild an inverse mapping table: encrypted position → original position Traverse every character in the ciphertext For letters, use the inverse mapping table to look up the original position (an O(1) lookup) Preserve non-letter characters unchanged Performance optimizations:\nUse an array instead of a HashMap for the mapping, which provides faster access Build the mapping table once so repeated lookups are efficient Language Choice: Why Rust? # Performance: compile to machine code with zero-cost abstractions, approaching C++ speed Safety: A strong type system prevents type-related vulnerabilities The ownership system eliminates memory problems const fn supports compile-time computation, reducing runtime overhead Ease of use: The clap library provides convenient CLI argument parsing Concise syntax and powerful pattern matching Helpful error messages and compiler diagnostics Rust Architecture and Cross-Platform Design # Rust Portability # affine-break is written entirely in Rust and has excellent cross-platform characteristics:\n1. Diverse compilation targets # Rust supports 70+ compilation targets through its LLVM backend, including:\nTarget platform Architecture Description x86_64-unknown-linux-gnu Linux x86-64 The most common server platform x86_64-pc-windows-msvc Windows x86-64 Uses the MSVC toolchain x86_64-apple-darwin macOS Intel Intel-based Mac aarch64-apple-darwin macOS Silicon Apple Silicon M1/M2 aarch64-unknown-linux-gnu Linux ARM64 Raspberry Pi and mobile devices armv7-unknown-linux-gnueabihf Linux ARM32 Embedded systems x86_64-pc-windows-gnu Windows MinGW No MSVC dependency wasm32-unknown-unknown WebAssembly Browser environments 2. Minimal dependencies # [dependencies] clap = { version = \u0026#34;4.5.34\u0026#34;, features = [\u0026#34;derive\u0026#34;] } affine-break has only one external dependency, clap (for CLI argument parsing), and no other indirect dependencies. This means:\n✅ Short build time (a few seconds) ✅ Small executable (only a few MB) ✅ No dynamic-library dependencies (fully statically linked) ✅ A reduced security surface 3. Zero runtime dependencies # Unlike Python and Node.js, a Rust-compiled binary:\nRequires no runtime environment Requires no dependency-package management Runs directly on the target machine Works out of the box Seamless Cross-Platform Compilation with the Zig Toolchain # Zig Compiler Advantages # Zig is a new language designed for systems programming, but its strongest feature is its general-purpose C/C++ compilation toolchain. This helps Rust developers by providing:\nZig = C/C++ 编译器 + 链接器 + 跨平台工具链 Why choose Zig instead of a traditional toolchain? # Tool Linux Windows macOS ARM Advantages Disadvantages GCC ✅ ⚠️ ❌ ✅ Broad support Cross-compilation is complex MSVC ❌ ✅ ❌ ❌ Native Windows support Windows only Clang ✅ ✅ ✅ ✅ General-purpose and powerful Requires multiple toolchains Zig compiler ✅ ✅ ✅ ✅ One toolchain handles everything Emerging project Key Features of the Zig Toolchain # 1. One universal toolchain # # 一个zig命令搞定所有平台编译 zig cc -target x86_64-linux-gnu main.c -o main-linux zig cc -target x86_64-windows-gnu main.c -o main.exe zig cc -target aarch64-macos main.c -o main-macos Rust/Zig integration (add this to .cargo/config.toml):\n[build] # 使用Zig作为C链接器 linker = \u0026#34;zig\u0026#34; rustflags = [\u0026#34;-C\u0026#34;, \u0026#34;link-arg=cc\u0026#34;, \u0026#34;-C\u0026#34;, \u0026#34;link-arg=-target\u0026#34;] [target.x86_64-unknown-linux-gnu] linker = \u0026#34;zig\u0026#34; rustflags = [\u0026#34;-C\u0026#34;, \u0026#34;link-arg=cc\u0026#34;, \u0026#34;-C\u0026#34;, \u0026#34;link-arg=-target\u0026#34;, \u0026#34;-C\u0026#34;, \u0026#34;link-arg=x86_64-linux-gnu\u0026#34;] [target.x86_64-pc-windows-gnu] linker = \u0026#34;zig\u0026#34; rustflags = [\u0026#34;-C\u0026#34;, \u0026#34;link-arg=cc\u0026#34;, \u0026#34;-C\u0026#34;, \u0026#34;link-arg=-target\u0026#34;, \u0026#34;-C\u0026#34;, \u0026#34;link-arg=x86_64-windows-gnu\u0026#34;] [target.aarch64-apple-darwin] linker = \u0026#34;zig\u0026#34; rustflags = [\u0026#34;-C\u0026#34;, \u0026#34;link-arg=cc\u0026#34;, \u0026#34;-C\u0026#34;, \u0026#34;link-arg=-target\u0026#34;, \u0026#34;-C\u0026#34;, \u0026#34;link-arg=aarch64-macos\u0026#34;] 2. Seamless cross-platform library support # Zig includes a complete C standard library, so different libc configurations are not needed for different platforms:\n// Rust代码可以安全跨平台 use std::fs; use std::process::Command; // 这些都能在任何平台上工作 fn main() { let content = fs::read_to_string(\u0026#34;test.txt\u0026#34;).unwrap(); let output = Command::new(\u0026#34;echo\u0026#34;).arg(\u0026amp;content).output().unwrap(); } 3. Static linking # # 编译为完全静态的可执行文件 RUSTFLAGS=\u0026#34;-C target-feature=+crt-static\u0026#34; \\ cargo build --target x86_64-unknown-linux-musl --release The result is a fully self-contained executable:\nDoes not depend on the system libc version Can run directly on any Linux distribution Can run even in a minimal Docker image Practical Cross-Platform Compilation Example # Scenario: Build for Windows and macOS on a Linux development machine # # 环境要求：仅需安装Zig编译器和Rust curl https://ziglang.org/builds/zig-linux-x86_64-latest.tar.xz | tar xJ # Linux x86-64 编译 cargo build --release --target x86_64-unknown-linux-gnu # Windows x86-64 编译（在Linux上） cargo build --release --target x86_64-pc-windows-gnu # macOS Intel 编译（在Linux上，需要macOS SDK） cargo build --release --target x86_64-apple-darwin # macOS ARM64编译（在Linux上，需要macOS SDK） cargo build --release --target aarch64-apple-darwin # ARM Linux编译（树莓派等） cargo build --release --target aarch64-unknown-linux-gnu Key point: everything is completed on a single development machine, without a virtual machine or remote build service.\nArchitecture Without External Dependencies # The Minimal affine-break Design # The project uses a minimalist architecture whose core functionality is implemented entirely in-house:\n// 所有密码学操作都是自己实现 const fn mod_space(x: i32) -\u0026gt; i32 const fn char_to_num(c: char) -\u0026gt; i32 const fn solve_a_and_b(...) fn affine_decrypt(...) Why not use an external cryptography library?\nSize: only a few hundred bytes are needed; a crypto library would add several MB Dependency chain: cryptography libraries commonly introduce 20+ indirect dependencies Simplicity: the mathematics of the affine cipher is simple enough that a self-contained implementation is clearer Educational value: it demonstrates cryptographic principles instead of making a black-box call CLI Framework Trade-offs # The only external dependency is clap (for command-line argument parsing):\n#[derive(Parser)] #[command( author = \u0026#34;DawnMagnet\u0026#34;, version, about = \u0026#34;...\u0026#34; )] struct Args { ciphertext: String, c1: char, x1: char, c2: char, x2: char, } Why use clap instead of writing the parser by hand?\nCompare the amount of code:\n// 用clap：5行代码 #[derive(Parser)] struct Args { ... } // 手写参数解析：50+行代码 fn main() { let args: Vec\u0026lt;String\u0026gt; = std::env::args().collect(); if args.len() \u0026lt; 6 { eprintln!(\u0026#34;Usage: ...\u0026#34;); return; } let ciphertext = \u0026amp;args[1]; let c1 = args[2].chars().next().unwrap(); // ... } The benefits of clap are worth the additional 1 KB of dependency size.\nComplete Static Compilation Guide # 1. Install the required tools # # 安装Zig编译器 curl -L https://ziglang.org/download/latest-dev/zig-linux-x86_64.tar.xz | tar xJ export PATH=$PWD/zig-linux-x86_64:$PATH # 验证 zig version rustc --version 2. Cargo configuration (optional, for automation) # Create .cargo/config.toml:\n[build] # 使用zig cc作为C链接器 cc = \u0026#34;zig cc\u0026#34; [target.x86_64-unknown-linux-gnu] linker = \u0026#34;zig\u0026#34; rustflags = [\u0026#34;-C\u0026#34;, \u0026#34;link-arg=cc\u0026#34;, \u0026#34;-C\u0026#34;, \u0026#34;link-arg=-target\u0026#34;, \u0026#34;-C\u0026#34;, \u0026#34;link-arg=x86_64-linux\u0026#34;] [target.x86_64-unknown-linux-musl] linker = \u0026#34;zig\u0026#34; rustflags = [\u0026#34;-C\u0026#34;, \u0026#34;link-arg=cc\u0026#34;, \u0026#34;-C\u0026#34;, \u0026#34;link-arg=-target\u0026#34;, \u0026#34;-C\u0026#34;, \u0026#34;link-arg=x86_64-linux-musl\u0026#34;] [target.aarch64-unknown-linux-gnu] linker = \u0026#34;zig\u0026#34; rustflags = [\u0026#34;-C\u0026#34;, \u0026#34;link-arg=cc\u0026#34;, \u0026#34;-C\u0026#34;, \u0026#34;link-arg=-target\u0026#34;, \u0026#34;-C\u0026#34;, \u0026#34;link-arg=aarch64-linux\u0026#34;] 3. Quick build script # Create build.sh:\n#!/bin/bash set -e PROJECT_NAME=\u0026#34;affine-break\u0026#34; TARGETS=( \u0026#34;x86_64-unknown-linux-gnu\u0026#34; \u0026#34;aarch64-unknown-linux-gnu\u0026#34; \u0026#34;x86_64-pc-windows-gnu\u0026#34; \u0026#34;x86_64-apple-darwin\u0026#34; \u0026#34;aarch64-apple-darwin\u0026#34; ) mkdir -p releases for target in \u0026#34;${TARGETS[@]}\u0026#34;; do echo \u0026#34;Compiling for $target...\u0026#34; cargo build -p \u0026#34;$PROJECT_NAME\u0026#34; --release --target \u0026#34;$target\u0026#34; # 确定可执行文件名 if [[ $target == *\u0026#34;windows\u0026#34;* ]]; then exe_name=\u0026#34;$PROJECT_NAME.exe\u0026#34; else exe_name=\u0026#34;$PROJECT_NAME\u0026#34; fi # 复制到releases目录 cp \u0026#34;target/$target/release/$exe_name\u0026#34; \\ \u0026#34;releases/$PROJECT_NAME-$target-${exe_name:-.exe}\u0026#34; done echo \u0026#34;✅ Build complete! Binaries in releases/\u0026#34; ls -lah releases/ 4. Automated cross-platform release with GitHub Actions # Create .github/workflows/release.yml:\nname: Cross-Platform Build on: push: tags: - \u0026#34;v*\u0026#34; jobs: build: runs-on: ${{ matrix.os }} strategy: matrix: include: - os: ubuntu-latest target: x86_64-unknown-linux-gnu - os: ubuntu-latest target: aarch64-unknown-linux-gnu - os: windows-latest target: x86_64-pc-windows-msvc - os: macos-latest target: x86_64-apple-darwin - os: macos-latest target: aarch64-apple-darwin steps: - uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: toolchain: stable target: ${{ matrix.target }} - name: Build run: cargo build -p affine-break --release --target ${{ matrix.target }} - name: Upload artifacts uses: actions/upload-artifact@v3 with: name: affine-break-${{ matrix.target }} path: target/${{ matrix.target }}/release/ After running this workflow, GitHub automatically:\nBuilds on multiple platforms Generates platform-specific binaries Uploads them as artifacts for download Release and Distribution # Installation from a User\u0026rsquo;s Perspective # # 一行命令安装（来自crates.io） cargo install affine-break # 或直接下载预编译二进制 wget https://github.com/DawnMagnet/ctf-tools-rs/releases/download/v1.5.0/affine-break-linux-x86_64 chmod +x affine-break-linux-x86_64 ./affine-break-linux-x86_64 \u0026#34;密文\u0026#34; c1 x1 c2 x2 Comparison # Distribution method Download size Dependencies Startup time Python script 10KB Requires Python + libraries 1–2 seconds Node.js tool 50KB Requires Node.js 0.5 seconds Java JAR 5MB Requires JRE 2–5 seconds Rust binary 3–5MB None \u0026lt;50ms Docker image 100MB+ Requires Docker Several seconds Performance Benchmarks # Actual performance on modern hardware (for a 100KB ciphertext):\nLinux x86-64: 12ms macOS ARM64: 15ms Windows AMD64: 13ms ARM Linux: 18ms Startup time (including argument parsing):\n\u0026lt; 1ms（本地SSD） \u0026lt; 2ms（网络存储） This is comparable to tools written in C or Go and is much faster than scripting languages.\nPractical Applications # 1. Affine Ciphers in CTF Competitions # Affine ciphers frequently appear in cryptography challenges in CTF competitions:\n题目：破解以下密文 Ciphertext: \u0026#34;uryyb jbeyq\u0026#34; Known plaintext: \u0026#34;h\u0026#34; → \u0026#34;u\u0026#34; and \u0026#34;w\u0026#34; → \u0026#34;j\u0026#34; Use the tool to solve it in one step:\naffine-break \u0026#34;uryyb jbeyq\u0026#34; u h j w 2. Cryptography Education # Demonstrate the principles of monoalphabetic substitution ciphers Show the power of known-plaintext attacks Understand the application of linear equations in cryptography 3. Historical Cipher Research # Apply it to breaking affine transformations in historical cipher systems.\nAdvanced Topics # How can the security of an affine cipher be improved? # Polyalphabetic substitution: use different keys to encrypt letters at different positions Add noise: mix in fake punctuation and digits Larger alphabet: include digits, symbols, and other characters to expand the key space Other Related Ciphers # Caesar cipher: a special case of the affine cipher (a=1) Extended Euclidean algorithm: the standard method for finding a modular multiplicative inverse Substitution cipher: a generalization of the affine cipher Summary # affine-break is a simple but powerful tool that demonstrates best practices in modern systems programming:\nTechnical Highlights # Cryptographic mathematics: linear congruences and modular arithmetic Cryptanalysis: the power of known-plaintext attacks Software design: efficient algorithms and data structures Rust programming: const fn, pattern matching, and memory safety Architectural Advantages # ┌─────────────────────────────────────┐ │ 纯Rust实现 + Zig工具链 │ ├─────────────────────────────────────┤ │ ✅ 零外部运行时依赖 │ │ ✅ 支持70+编译目标（一行命令跨平台） │ │ ✅ 完全静态链接（任意Linux/Windows） │ │ ✅ 编译文件小（3-5MB） │ │ ✅ 启动秒杀Python/Node.js(\u0026lt;1ms) │ │ ✅ 内存安全（无缓冲区溢出风险） │ └─────────────────────────────────────┘ Why this combination is future-oriented # Container-friendly: no runtime needs to be preinstalled in the base image Cloud-native: fast cold starts, suitable for serverless workloads Edge computing: native ARM support with no additional dependencies Security: one binary means one auditable attack surface Maintainability: a single language stack reduces toolchain complexity For CTF enthusiasts and people learning cryptography, this tool is both a practical cracking scaffold and an excellent reference implementation for studying cryptographic principles.\nPractical Deployment Guide # Quick Start # Method 1: Use Cargo (recommended) # # 安装Rust（首次） curl --proto \u0026#39;=https\u0026#39; --tlsv1.2 -sSf https://sh.rustup.rs | sh # 安装affine-break cargo install affine-break # 使用 affine-break \u0026#34;密文\u0026#34; 密文字符1 明文字符1 密文字符2 明文字符2 Advantage: one-command installation that automatically selects the best compilation target for the local machine\nMethod 2: Build from source (custom) # # 克隆项目 git clone https://github.com/DawnMagnet/ctf-tools-rs.git cd ctf-tools-rs/affine-break # 编译 cargo build --release # 运行 ./target/release/affine-break \u0026#34;密文\u0026#34; c1 x1 c2 x2 Use case: modifying the source code, studying the implementation, or trimming dependencies\nMethod 3: Precompiled binary (fastest) # Download directly from GitHub Releases:\n# Linux wget https://github.com/DawnMagnet/ctf-tools-rs/releases/download/v1.5.0/affine-break-linux-x86_64 chmod +x affine-break-linux-x86_64 ./affine-break-linux-x86_64 \u0026#34;密文\u0026#34; c1 x1 c2 x2 # macOS (Intel) wget https://github.com/DawnMagnet/ctf-tools-rs/releases/download/v1.5.0/affine-break-macos-x86_64 # macOS (Apple Silicon) wget https://github.com/DawnMagnet/ctf-tools-rs/releases/download/v1.5.0/affine-break-macos-aarch64 # Windows # 下载 affine-break-windows-x86_64.exe Advantage: starts in seconds, requires no compilation, and can be used offline\nDocker Deployment (optional) # To use it in a container:\n# Dockerfile FROM scratch COPY --from=rust:1.75-alpine AS builder WORKDIR /build COPY . . RUN cargo build --release FROM scratch COPY --from=builder /build/target/release/affine-break /affine-break ENTRYPOINT [\u0026#34;/affine-break\u0026#34;] Build and run:\ndocker build -t affine-break . docker run --rm affine-break \u0026#34;密文\u0026#34; c1 x1 c2 x2 Image size: only 5–8 MB when using a scratch base image\nCI/CD Integration # Integrate affine-break into automated tools:\nUse from a shell script # #!/bin/bash CIPHERTEXT=\u0026#34;prwy{w14wf3p5-fo6w-11gf-w02o-88g9pg5197wo}\u0026#34; PLAINTEXT=$(affine-break \u0026#34;$CIPHERTEXT\u0026#34; p f r l) echo \u0026#34;Decrypted: $PLAINTEXT\u0026#34; Call from Python # import subprocess def break_affine(ciphertext, c1, x1, c2, x2): result = subprocess.run( [\u0026#39;affine-break\u0026#39;, ciphertext, c1, x1, c2, x2], capture_output=True, text=True ) return result.stdout.strip() plaintext = break_affine(\u0026#34;prwy{w14wf3p5-fo6w-11gf-w02o-88g9pg5197wo}\u0026#34;, \u0026#39;p\u0026#39;, \u0026#39;f\u0026#39;, \u0026#39;r\u0026#39;, \u0026#39;l\u0026#39;) print(plaintext) # flag{a14ab3f5-bc6a-11eb-a02c-88e9fe5197ac} MacBook M-series integration (iOS Shortcut) # It can be installed with Homebrew and integrated into the Shortcut app to provide a one-tap cracking experience on mobile.\nPerformance Optimization Suggestions # Batch Cracking Optimization # If you need to try multiple plaintext-ciphertext character pairs:\n#!/bin/bash CIPHERTEXT=\u0026#34;prwy{w14wf3p5-fo6w-11gf-w02o-88g9pg5197wo}\u0026#34; # 尝试常见的词对 pairs=( \u0026#34;p f r l\u0026#34; # p-\u0026gt;f, r-\u0026gt;l \u0026#34;w f o l\u0026#34; # w-\u0026gt;f, o-\u0026gt;l \u0026#34;y a w t\u0026#34; # y-\u0026gt;a, w-\u0026gt;t ) for pair in \u0026#34;${pairs[@]}\u0026#34;; do echo \u0026#34;Trying: $pair\u0026#34; affine-break \u0026#34;$CIPHERTEXT\u0026#34; $pair \u0026amp;\u0026amp; break done Parallel Processing (large ciphertexts) # # 对多个密文并行破解 cat ciphertexts.txt | xargs -I {} -P 4 \\ affine-break {} p f r l -P 4: uses four parallel processes; adjust this according to the number of CPU cores.\nTroubleshooting # Q: \u0026ldquo;No solution found\u0026rdquo; error # Cause: the supplied plaintext-ciphertext pair does not match\nSolution:\nCheck that the input characters are correct Try other known character pairs Check that the ciphertext was actually encrypted with an affine cipher # 如果不确定，尝试bruteforce验证 # 生成所有可能的 a,b 组合并尝试解密 for a in {1..25}; do for b in {0..25}; do echo \u0026#34;Testing a=$a, b=$b\u0026#34; # 这部分需要自己实现或修改工具 done done Q: Cross-platform compilation failed # Symptom: error: could not compile dependency\nSolution:\n# 清理旧的构建缓存 cargo clean # 更新工具链 rustup update # 指定特定目标后重试 cargo build --release --target x86_64-unknown-linux-gnu Q: How can I verify the decryption result? # # 手动验证密钥 plaintext=\u0026#34;flag\u0026#34; ciphertext=\u0026#34;prwy\u0026#34; # 计算加密参数（如果已知） echo \u0026#34;若 ${plaintext[0]} (${plaintext:0:1}) -\u0026gt; ${ciphertext[0]} 与已知密钥相符，则正确\u0026#34; Advanced Usage # Modify the source to support a custom alphabet # If you want to support Chinese, Japanese, or another character set:\n// 修改 const fn char_to_num 以支持更大的字母表 const fn char_to_num_extended(c: char) -\u0026gt; i32 { // 支持 0-65535 范围的Unicode字符 c as i32 } // 修改 mod_space 来处理更大的模数 const fn mod_space_extended(x: i32, modulus: i32) -\u0026gt; i32 { x.rem_euclid(modulus) } Performance tuning # // 使用inline宏减少函数调用开销 #[inline(always)] const fn mod_space(x: i32) -\u0026gt; i32 { x.rem_euclid(26) } // 在热路径中使用SIMD（针对大文本） // 当前实现已足够快，但可深入优化 Related Resources # Rust official documentation Zig compiler Cargo package manager Affine cipher explained CTF cryptography resources Cross-platform Rust applications Disclaimer # This tool is intended only for education and authorized security testing. Decrypting someone else\u0026rsquo;s information without authorization is illegal. Make sure you use it only with appropriate permission and consent.\n","date":"Feb 24, 2026","externalUrl":null,"permalink":"/en/ctf/crypto/affine-break/","section":"CTF Notes","summary":"","title":"Affine Cipher Analysis Tool Explained","type":"ctf"},{"content":"","date":"Feb 24, 2026","externalUrl":null,"permalink":"/en/ctf/crypto/","section":"CTF Notes","summary":"","title":"Cryptography","type":"ctf"},{"content":"","date":"Feb 24, 2026","externalUrl":null,"permalink":"/en/tags/cryptography/","section":"Tags","summary":"","title":"Cryptography","type":"tags"},{"content":"","date":"Feb 24, 2026","externalUrl":null,"permalink":"/en/tags/ctf/","section":"Tags","summary":"","title":"CTF","type":"tags"},{"content":"English translations of cryptography and file-forensics notes.\n","date":"Feb 24, 2026","externalUrl":null,"permalink":"/en/ctf/","section":"CTF Notes","summary":"","title":"CTF Notes","type":"ctf"},{"content":"","date":"Feb 24, 2026","externalUrl":null,"permalink":"/en/categories/cybersecurity/","section":"Categories","summary":"","title":"Cybersecurity","type":"categories"},{"content":"","date":"Feb 24, 2026","externalUrl":null,"permalink":"/en/tags/rust/","section":"Tags","summary":"","title":"Rust","type":"tags"},{"content":" Rust Code Template # use std::collections::HashMap; pub use __cargo_equip::prelude::*; #[allow(unused_imports)] use proconio::fastout; use proconio::input; // #[fastout] fn solve() { // write your solution here! } fn main() { input! { t: usize } for _ in 0..t { solve(); } } // The following code was expanded by `cargo-equip`. #[cfg_attr(any(), rustfmt::skip)] #[allow(unused)] mod __cargo_equip { pub(crate) mod crates { pub mod __algo_0_1_0 {pub use crate::__cargo_equip::macros::__algo_0_1_0::*;pub mod math{pub mod primes{use super::Integer;pub trait PrimeExt:Integer{fn is_prime(\u0026amp;self)-\u0026gt;bool{if*self\u0026lt;Self::ZERO{panic!(\u0026#34;failed to check whether integer \u0026#39;{:?}\u0026#39; is a prime number, because it is smaller than zero for which this function is undefined\u0026#34;,self);}if*self==Self::ZERO||*self==Self::ONE{return false;}let mut cur=Self::from_i64(2);while cur*cur\u0026lt;=*self{if*self%cur==Self::ZERO{return false;}cur=cur+Self::ONE;}true}fn factorize(\u0026amp;self)-\u0026gt;Vec\u0026lt;Self\u0026gt;{if*self\u0026lt;Self::ZERO{panic!(\u0026#34;failed to find prime factors of the integer \u0026#39;{:?}\u0026#39;, because it is smaller than zero for which this function is undefined\u0026#34;,self);}let mut result=vec![];let mut k=Self::from_i64(2);let mut n=*self;while k*k\u0026lt;=*self{while n%k==Self::ZERO{result.push(k);n=n/k;}k=k+Self::ONE;}if n\u0026gt;Self::ONE{result.push(n);}result}}impl\u0026lt;T:Integer\u0026gt;PrimeExt for T{}}pub mod integer{use std::{ops::{Mul,Div,Rem,Add,Sub},fmt::{Display,Debug}};pub trait Integer:Sized+Mul\u0026lt;Self,Output=Self\u0026gt;+Div\u0026lt;Self,Output=Self\u0026gt;+Rem\u0026lt;Self,Output=Self\u0026gt;+Add\u0026lt;Self,Output=Self\u0026gt;+Sub\u0026lt;Self,Output=Self\u0026gt;+PartialEq+Eq+Ord+PartialOrd+Copy+Clone+Display+Debug{const ONE:Self;const ZERO:Self;fn from_i64(val:i64)-\u0026gt;Self;}macro_rules!impl_integer{($t:ty)=\u0026gt;{impl Integer for$t{const ONE:Self=1;const ZERO:Self=0;fn from_i64(val:i64)-\u0026gt;Self{val as$t}}};}impl_integer!(usize);impl_integer!(isize);impl_integer!(i32);impl_integer!(i64);impl_integer!(u32);impl_integer!(u64);}pub use integer::Integer;pub mod modular{use std::{ops::{Add,Mul,Sub,Div,AddAssign,MulAssign,SubAssign,DivAssign},fmt::Display};#[derive(Copy,Clone,Default,Debug,PartialEq,PartialOrd,Eq,Ord)]pub struct MInt\u0026lt;const MODULUS:u64\u0026gt;{pub value:u64}impl\u0026lt;const M:u64\u0026gt;Display for MInt\u0026lt;M\u0026gt;{fn fmt(\u0026amp;self,f:\u0026amp;mut std::fmt::Formatter\u0026lt;\u0026#39;_\u0026gt;)-\u0026gt;std::fmt::Result{write!(f,\u0026#34;{}\u0026#34;,self.value)}}impl\u0026lt;const MODULUS:u64\u0026gt;MInt\u0026lt;MODULUS\u0026gt;{pub fn one()-\u0026gt;Self{Self{value:1}}pub fn zero()-\u0026gt;Self{Self{value:0}}pub fn new(value:u64)-\u0026gt;Self{Self{value:value%MODULUS}}pub fn pow(self,n:u64)-\u0026gt;MInt\u0026lt;MODULUS\u0026gt;{let mut result=Self::one();let mut base=self;let mut exponent=n;while exponent\u0026gt;0{if exponent%2==1{result=result*base;}base=base*base;exponent/=2;}result}fn extended_gcd(a:i64,b:i64)-\u0026gt;(i64,i64,i64){if a==0{(b,0,1)}else{let(g,x,y)=Self::extended_gcd(b%a,a);(g,y-(b/a)*x,x)}}pub fn inv(self)-\u0026gt;Self{let(_,x,_)=Self::extended_gcd(self.value as i64,MODULUS as i64);Self::new((x+MODULUS as i64)as u64)}}impl\u0026lt;const T:u64\u0026gt;Add\u0026lt;MInt\u0026lt;T\u0026gt;\u0026gt;for MInt\u0026lt;T\u0026gt;{type Output=MInt\u0026lt;T\u0026gt;;fn add(self,rhs:MInt\u0026lt;T\u0026gt;)-\u0026gt;Self::Output{let mut value=self.value+rhs.value;if value\u0026gt;=T{value-=T;}Self{value}}}impl\u0026lt;const T:u64\u0026gt;AddAssign\u0026lt;MInt\u0026lt;T\u0026gt;\u0026gt;for MInt\u0026lt;T\u0026gt;{fn add_assign(\u0026amp;mut self,rhs:MInt\u0026lt;T\u0026gt;){*self=*self+rhs;}}impl\u0026lt;const T:u64\u0026gt;Mul\u0026lt;MInt\u0026lt;T\u0026gt;\u0026gt;for MInt\u0026lt;T\u0026gt;{type Output=MInt\u0026lt;T\u0026gt;;fn mul(self,rhs:MInt\u0026lt;T\u0026gt;)-\u0026gt;Self::Output{Self{value:(self.value*rhs.value)%T}}}impl\u0026lt;const T:u64\u0026gt;MulAssign\u0026lt;MInt\u0026lt;T\u0026gt;\u0026gt;for MInt\u0026lt;T\u0026gt;{fn mul_assign(\u0026amp;mut self,rhs:MInt\u0026lt;T\u0026gt;){self.value=(self.value*rhs.value)%T;}}impl\u0026lt;const T:u64\u0026gt;Sub\u0026lt;MInt\u0026lt;T\u0026gt;\u0026gt;for MInt\u0026lt;T\u0026gt;{type Output=MInt\u0026lt;T\u0026gt;;fn sub(self,rhs:MInt\u0026lt;T\u0026gt;)-\u0026gt;Self::Output{let mut value=self.value+T-rhs.value;if value\u0026gt;=T{value-=T;}Self{value}}}impl\u0026lt;const T:u64\u0026gt;SubAssign\u0026lt;MInt\u0026lt;T\u0026gt;\u0026gt;for MInt\u0026lt;T\u0026gt;{fn sub_assign(\u0026amp;mut self,rhs:MInt\u0026lt;T\u0026gt;){*self=*self-rhs;}}impl\u0026lt;const T:u64\u0026gt;Div\u0026lt;MInt\u0026lt;T\u0026gt;\u0026gt;for MInt\u0026lt;T\u0026gt;{type Output=MInt\u0026lt;T\u0026gt;;fn div(self,rhs:MInt\u0026lt;T\u0026gt;)-\u0026gt;Self::Output{self*rhs.inv()}}impl\u0026lt;const T:u64\u0026gt;DivAssign\u0026lt;MInt\u0026lt;T\u0026gt;\u0026gt;for MInt\u0026lt;T\u0026gt;{fn div_assign(\u0026amp;mut self,rhs:MInt\u0026lt;T\u0026gt;){*self=*self/rhs;}}impl\u0026lt;const T:u64\u0026gt;Into\u0026lt;MInt\u0026lt;T\u0026gt;\u0026gt;for u64{fn into(self)-\u0026gt;MInt\u0026lt;T\u0026gt;{MInt::new(self)}}}pub fn gcd\u0026lt;T:Integer\u0026gt;(mut a:T,mut b:T)-\u0026gt;T{if a\u0026gt;b{std::mem::swap(\u0026amp;mut a,\u0026amp;mut b);}while a!=T::ZERO{b=b%a;std::mem::swap(\u0026amp;mut a,\u0026amp;mut b);}b}pub fn lcm\u0026lt;T:Integer\u0026gt;(a:T,b:T)-\u0026gt;T{a/gcd(a,b)*b}}pub mod collections{pub mod segment_tree{use std::ops::{Range,RangeBounds};pub struct SegmentTree\u0026lt;T,F\u0026gt;{n:usize,data:Vec\u0026lt;T\u0026gt;,neutral:T,f:F,}impl\u0026lt;T,F\u0026gt;SegmentTree\u0026lt;T,F\u0026gt;where T:Clone,F:Fn(\u0026amp;T,\u0026amp;T)-\u0026gt;T,{pub fn new(n:usize,neutral:T,f:F)-\u0026gt;Self{let mut size=1;while size\u0026lt;n{size*=2;}Self{n:size,data:vec![neutral.clone();2*size],neutral,f,}}pub fn new_from_iter\u0026lt;I\u0026gt;(iter:I,neutral:T,f:F)-\u0026gt;Self where I:IntoIterator\u0026lt;Item=T\u0026gt;,{let v:Vec\u0026lt;_\u0026gt; =iter.into_iter().collect();let mut size=1;while size\u0026lt;v.len(){size\u0026lt;\u0026lt;=1;}let mut data=vec![neutral.clone();size\u0026lt;\u0026lt;1];for i in 0..v.len(){data[size+i]=v[i].clone();}for i in(1..size).rev(){data[i]=(f)(\u0026amp;data[i\u0026lt;\u0026lt;1],\u0026amp;data[(i\u0026lt;\u0026lt;1)+1]);}Self{n:size,data,neutral,f,}}pub fn update(\u0026amp;mut self,i:usize,value:T){let mut i=i+self.n;self.data[i]=value;while i\u0026gt;1{i\u0026gt;\u0026gt;=1;self.data[i]=(self.f)(\u0026amp;self.data[i\u0026lt;\u0026lt;1],\u0026amp;self.data[(i\u0026lt;\u0026lt;1)+1]);}}pub fn get(\u0026amp;self,i:usize)-\u0026gt;\u0026amp;T{\u0026amp;self.data[i+self.n]}pub fn query(\u0026amp;self,range:impl RangeBounds\u0026lt;usize\u0026gt;)-\u0026gt;T{self.query_inner(range,1,..)}fn to_range(\u0026amp;self,range:impl RangeBounds\u0026lt;usize\u0026gt;)-\u0026gt;Range\u0026lt;usize\u0026gt;{let start=match range.start_bound(){std::ops::Bound::Included(\u0026amp;p)=\u0026gt;p,std::ops::Bound::Excluded(\u0026amp;p)=\u0026gt;p+1,std::ops::Bound::Unbounded=\u0026gt;0,};let end=match range.end_bound(){std::ops::Bound::Included(\u0026amp;p)=\u0026gt;p+1,std::ops::Bound::Excluded(\u0026amp;p)=\u0026gt;p,std::ops::Bound::Unbounded=\u0026gt;self.n,};start..end}fn query_inner(\u0026amp;self,range:impl RangeBounds\u0026lt;usize\u0026gt;,i:usize,inner_range:impl RangeBounds\u0026lt;usize\u0026gt;)-\u0026gt;T{let range=self.to_range(range);let inner_range=self.to_range(inner_range);if range.start\u0026gt;=range.end{return self.neutral.clone();}if range.start==inner_range.start\u0026amp;\u0026amp;range.end==inner_range.end{return self.data[i].clone();}let mid=(inner_range.start+inner_range.end)\u0026gt;\u0026gt;1;let left=self.query_inner(range.start..mid.min(range.end),i\u0026lt;\u0026lt;1,inner_range.start..mid);let right=self.query_inner(mid.max(range.start)..range.end,(i\u0026lt;\u0026lt;1)+1,mid..inner_range.end);(self.f)(\u0026amp;left,\u0026amp;right)}pub fn data(\u0026amp;self)-\u0026gt;\u0026amp;[T]{\u0026amp;self.data[self.n..]}}pub struct SegmentTreeRU\u0026lt;T,F,G,H\u0026gt;{n:usize,data:Vec\u0026lt;T\u0026gt;,lazy:Vec\u0026lt;Option\u0026lt;T\u0026gt;\u0026gt;,neutral:T,f:F,g:G,h:H}impl\u0026lt;T,F,G,H\u0026gt;SegmentTreeRU\u0026lt;T,F,G,H\u0026gt;where T:Clone+Copy,F:Fn(\u0026amp;T,\u0026amp;T)-\u0026gt;T,G:Fn(\u0026amp;T,\u0026amp;T,usize)-\u0026gt;T,H:Fn(\u0026amp;T,\u0026amp;T)-\u0026gt;T{pub fn new(n:usize,neutral:T,f:F,g:G,h:H)-\u0026gt;Self{let mut size=1;while size\u0026lt;n{size*=2;}Self{n:size,data:vec![neutral.clone();size*2],lazy:vec![None;size*2],neutral,f,g,h}}pub fn new_from_iter\u0026lt;I\u0026gt;(iter:I,neutral:T,f:F,g:G,h:H)-\u0026gt;Self where I:IntoIterator\u0026lt;Item=T\u0026gt;{let v:Vec\u0026lt;_\u0026gt; =iter.into_iter().collect();let mut size=1;while size\u0026lt;v.len(){size*=2;}let mut data=vec![neutral.clone();2*size];for(i,val)in v.into_iter().enumerate(){data[size+i]=val;}for i in(1..size).rev(){data[i]=(f)(\u0026amp;data[2*i],\u0026amp;data[2*i+1]);}Self{n:size,data,lazy:vec![None;2*size],neutral,f,g,h,}}pub fn query(\u0026amp;mut self,range:impl RangeBounds\u0026lt;usize\u0026gt;)-\u0026gt;T{self.query_inner(self.to_range(range),1,self.to_range(..))}fn propagate(\u0026amp;mut self,i:usize,inner_range:Range\u0026lt;usize\u0026gt;){let Some(lazy)=self.lazy[i].clone()else{return;};self.data[i]=(self.g)(\u0026amp;self.data[i],\u0026amp;lazy,inner_range.end-inner_range.start);if inner_range.end-inner_range.start!=1{if let Some(child_lazy)=\u0026amp;self.lazy[i*2]{self.lazy[i*2]=Some((self.h)(child_lazy,\u0026amp;lazy));}else{self.lazy[i*2]=Some(lazy.clone());}if let Some(child_lazy)=\u0026amp;self.lazy[i*2+1]{self.lazy[i*2+1]=Some((self.h)(child_lazy,\u0026amp;lazy));}else{self.lazy[i*2+1]=Some(lazy.clone());}}self.lazy[i]=None;}fn query_inner(\u0026amp;mut self,range:Range\u0026lt;usize\u0026gt;,i:usize,inner_range:Range\u0026lt;usize\u0026gt;)-\u0026gt;T{self.propagate(i,inner_range.clone());if range.start\u0026gt;=inner_range.end||inner_range.start\u0026gt;=range.end{return self.neutral.clone();}if range.start\u0026lt;=inner_range.start\u0026amp;\u0026amp;inner_range.end\u0026lt;=range.end{return self.data[i];}let mid=(inner_range.start+inner_range.end)/2;let left=self.query_inner(range.clone(),i*2,inner_range.start..mid);let right=self.query_inner(range,i*2+1,mid..inner_range.end);(self.f)(\u0026amp;left,\u0026amp;right)}pub fn update(\u0026amp;mut self,range:impl RangeBounds\u0026lt;usize\u0026gt;,val:T){self.update_inner(self.to_range(range),val,1,self.to_range(..));}fn update_inner(\u0026amp;mut self,range:Range\u0026lt;usize\u0026gt;,val:T,i:usize,inner_range:Range\u0026lt;usize\u0026gt;){self.propagate(i,inner_range.clone());if range.end\u0026lt;=inner_range.start||inner_range.end\u0026lt;=range.start{return;}if range.start\u0026lt;=inner_range.start\u0026amp;\u0026amp;inner_range.end\u0026lt;=range.end{self.lazy[i]=Some(val.clone());self.propagate(i,inner_range);return;}let mid=(inner_range.start+inner_range.end)/2;self.update_inner(range.clone(),val,i*2,inner_range.start..mid);self.update_inner(range,val,i*2+1,mid..inner_range.end);self.data[i]=(self.f)(\u0026amp;self.data[i*2],\u0026amp;self.data[i*2+1]);}fn to_range(\u0026amp;self,range:impl RangeBounds\u0026lt;usize\u0026gt;)-\u0026gt;Range\u0026lt;usize\u0026gt;{let start=match range.start_bound(){std::ops::Bound::Included(\u0026amp;p)=\u0026gt;p,std::ops::Bound::Excluded(\u0026amp;p)=\u0026gt;p+1,std::ops::Bound::Unbounded=\u0026gt;0,};let end=match range.end_bound(){std::ops::Bound::Included(\u0026amp;p)=\u0026gt;p+1,std::ops::Bound::Excluded(\u0026amp;p)=\u0026gt;p,std::ops::Bound::Unbounded=\u0026gt;self.n,};start..end}}}pub mod treap{use std::mem;use super::super::misc::random::rand_u64;pub enum TreapNodeCont\u0026lt;T:PartialOrd\u0026gt;{Some(Box\u0026lt;TreapNode\u0026lt;T\u0026gt;\u0026gt;),Empty}impl\u0026lt;T:PartialOrd\u0026gt;Default for TreapNodeCont\u0026lt;T\u0026gt;{fn default()-\u0026gt;Self{TreapNodeCont::Empty}}pub struct Treap\u0026lt;T:PartialOrd\u0026gt;{root:TreapNodeCont\u0026lt;T\u0026gt;,}impl\u0026lt;T:Clone+PartialOrd\u0026gt;Treap\u0026lt;T\u0026gt;{pub fn new()-\u0026gt;Self{Self{root:TreapNodeCont::Empty,}}pub fn from_root(root:TreapNodeCont\u0026lt;T\u0026gt;)-\u0026gt;Self{Self{root,}}pub fn split(self,x:T)-\u0026gt;(Treap\u0026lt;T\u0026gt;,Treap\u0026lt;T\u0026gt;){let(left_root,right_root)=self.root.split(x);(Treap::from_root(left_root),Treap::from_root(right_root))}pub fn insert(\u0026amp;mut self,key:T){let root=mem::take(\u0026amp;mut self.root);self.root=root.insert(TreapNode::from_key(key));}pub fn merge(self,other:Treap\u0026lt;T\u0026gt;)-\u0026gt;Treap\u0026lt;T\u0026gt;{let new_root=self.root.merge(other.root);Self{root:new_root}}pub fn erase(\u0026amp;mut self,key:\u0026amp;T){let root=mem::take(\u0026amp;mut self.root);self.root=root.erase(key);}pub fn contains(\u0026amp;self,key:\u0026amp;T)-\u0026gt;bool{self.root.contains(key)}pub fn len(\u0026amp;self)-\u0026gt;usize{self.root.len()}}pub struct TreapNode\u0026lt;T:PartialOrd\u0026gt;{key:T,left:TreapNodeCont\u0026lt;T\u0026gt;,right:TreapNodeCont\u0026lt;T\u0026gt;,priority:u64,len:usize}impl\u0026lt;T:PartialOrd+Clone\u0026gt;TreapNode\u0026lt;T\u0026gt;{pub fn from_key(key:T)-\u0026gt;Self{Self{key,left:TreapNodeCont::Empty,right:TreapNodeCont::Empty,priority:rand_u64(),len:1}}fn recompute(\u0026amp;mut self){self.len=self.left.len()+self.right.len()+1;}}impl\u0026lt;T:PartialOrd+Clone\u0026gt;TreapNodeCont\u0026lt;T\u0026gt;{fn len(\u0026amp;self)-\u0026gt;usize{if let TreapNodeCont::Some(root)=self{root.len}else{0}}fn split(self,x:T)-\u0026gt;(TreapNodeCont\u0026lt;T\u0026gt;,TreapNodeCont\u0026lt;T\u0026gt;){let Self::Some(mut root)=self else{return(Self::Empty,Self::Empty);};let(left_res,right_res);if root.key\u0026gt;x{(left_res,root.left)=root.left.split(x);root.len=root.left.len()+root.right.len();root.recompute();right_res=TreapNodeCont::Some(root);}else{(root.right,right_res)=root.right.split(x);root.recompute();left_res=TreapNodeCont::Some(root);}(left_res,right_res)}fn insert(self,mut single_node:TreapNode\u0026lt;T\u0026gt;)-\u0026gt;TreapNodeCont\u0026lt;T\u0026gt;{let TreapNodeCont::Some(mut root)=self else{return TreapNodeCont::Some(Box::new(single_node));};if single_node.priority\u0026gt;=root.priority{(single_node.left,single_node.right)=TreapNodeCont::Some(root).split(single_node.key.clone());single_node.recompute();TreapNodeCont::Some(Box::new(single_node))}else{if single_node.key\u0026lt;=root.key{root.left=root.left.insert(single_node);}else{root.right=root.right.insert(single_node);}root.recompute();TreapNodeCont::Some(root)}}fn contains(\u0026amp;self,key:\u0026amp;T)-\u0026gt;bool{let TreapNodeCont::Some(root)=self else{return false;};match key.partial_cmp(\u0026amp;root.key).unwrap(){std::cmp::Ordering::Less=\u0026gt;{root.left.contains(key)},std::cmp::Ordering::Greater=\u0026gt;{root.right.contains(key)},std::cmp::Ordering::Equal=\u0026gt;{true},}}fn erase(self,key:\u0026amp;T)-\u0026gt;TreapNodeCont\u0026lt;T\u0026gt;{let TreapNodeCont::Some(mut root)=self else{return TreapNodeCont::Empty;};match key.partial_cmp(\u0026amp;root.key).unwrap(){std::cmp::Ordering::Less=\u0026gt;{root.left=root.left.erase(key);root.recompute();TreapNodeCont::Some(root)},std::cmp::Ordering::Greater=\u0026gt;{root.right=root.right.erase(key);root.recompute();TreapNodeCont::Some(root)},std::cmp::Ordering::Equal=\u0026gt;{let left_subtree=mem::take(\u0026amp;mut root.left);let right_subtree=mem::take(\u0026amp;mut root.right);left_subtree.merge(right_subtree)},}}fn merge(self,other:TreapNodeCont\u0026lt;T\u0026gt;)-\u0026gt;TreapNodeCont\u0026lt;T\u0026gt;{let TreapNodeCont::Some(mut left_root)=self else{return other;};let TreapNodeCont::Some(mut right_root)=other else{return TreapNodeCont::Some(left_root);};if left_root.priority\u0026gt;=right_root.priority{let(left_child,right_child)=(mem::take(\u0026amp;mut left_root.left),mem::take(\u0026amp;mut left_root.right));left_root.left=left_child.merge(right_child);left_root.right=TreapNodeCont::Some(right_root);left_root.recompute();TreapNodeCont::Some(left_root)}else{let(left_child,right_child)=(mem::take(\u0026amp;mut right_root.left),mem::take(\u0026amp;mut right_root.right));right_root.right=left_child.merge(right_child);right_root.left=TreapNodeCont::Some(left_root);right_root.recompute();TreapNodeCont::Some(right_root)}}}}pub mod disjoint_set{pub struct DisjointSet{data:Vec\u0026lt;usize\u0026gt;,size:Vec\u0026lt;usize\u0026gt;}impl DisjointSet{pub fn new(n:usize)-\u0026gt;Self{Self{data:(0..n).collect(),size:vec![1;n]}}pub fn find(\u0026amp;mut self,mut x:usize)-\u0026gt;usize{if self.data[x]!=x{x=self.find(self.data[x]);self.data[x]=x;}x}pub fn join(\u0026amp;mut self,mut x:usize,mut y:usize)-\u0026gt;bool{x=self.find(x);y=self.find(y);if x==y{return false;}if self.size[x]\u0026lt;self.size[y]{std::mem::swap(\u0026amp;mut x,\u0026amp;mut y);}self.size[x]+=self.size[y];self.data[y]=x;true}pub fn size(\u0026amp;mut self,x:usize)-\u0026gt;usize{let x=self.find(x);self.size[x]}pub fn len(\u0026amp;self)-\u0026gt;usize{self.data.len()}}}}pub mod misc{pub mod random{use std::time::SystemTime;pub static mut RNG:Option\u0026lt;XorShift\u0026gt; =None;pub fn rand_u64()-\u0026gt;u64{let rng=unsafe{RNG.get_or_insert(XorShift::new((SystemTime::UNIX_EPOCH.elapsed().unwrap().as_nanos()\u0026amp;0xFFFFFFFFFFFFFFFF)as u64))};rng.next()}pub struct XorShift{x:u64,y:u64,z:u64,w:u64,}impl XorShift{pub fn new(seed:u64)-\u0026gt;Self{XorShift{x:9018237498,y:1982731389,z:1894712904,w:seed,}}pub fn next(\u0026amp;mut self)-\u0026gt;u64{let t=self.x^(self.x\u0026lt;\u0026lt;11);self.x=self.y;self.y=self.z;self.z=self.w;self.w=self.w^(self.w\u0026gt;\u0026gt;19)^t^(t\u0026gt;\u0026gt;8);self.w}}}pub mod stdout{#[macro_export]macro_rules!__cargo_equip_macro_def___algo_0_1_0_println_iter{($iter:expr)=\u0026gt;{for val in$iter{print!(\u0026#34;{} \u0026#34;,val);}println!();};}macro_rules!println_iter{($($tt:tt)*)=\u0026gt;(crate::__cargo_equip_macro_def___algo_0_1_0_println_iter!{$($tt)*})}}pub mod mim{#[macro_export]macro_rules!__cargo_equip_macro_def___algo_0_1_0_maxim{($a:expr,$b:expr)=\u0026gt;{if$b\u0026gt;$a{$a=$b;}};}macro_rules!maxim{($($tt:tt)*)=\u0026gt;(crate::__cargo_equip_macro_def___algo_0_1_0_maxim!{$($tt)*})}#[macro_export]macro_rules!__cargo_equip_macro_def___algo_0_1_0_minim{($a:expr,$b:expr)=\u0026gt;{if$b\u0026lt;$a{$a=$b;}};}macro_rules!minim{($($tt:tt)*)=\u0026gt;(crate::__cargo_equip_macro_def___algo_0_1_0_minim!{$($tt)*})}}}} pub mod codeforces {} pub mod proconio {#![allow(clippy::needless_doctest_main,clippy::print_literal)]use crate::__cargo_equip::preludes::proconio::*;pub use crate::__cargo_equip::macros::proconio::*;pub use proconio_derive::*;pub mod marker{use crate::__cargo_equip::preludes::proconio::*;use crate::__cargo_equip::crates::proconio::source::{Readable,Source};use std::io::BufRead;pub enum Chars{}impl Readable for Chars{type Output=Vec\u0026lt;char\u0026gt;;fn read\u0026lt;R:BufRead,S:Source\u0026lt;R\u0026gt;\u0026gt;(source:\u0026amp;mut S)-\u0026gt;Vec\u0026lt;char\u0026gt;{source.next_token_unwrap().chars().collect()}}pub enum Bytes{}impl Readable for Bytes{type Output=Vec\u0026lt;u8\u0026gt;;fn read\u0026lt;R:BufRead,S:Source\u0026lt;R\u0026gt;\u0026gt;(source:\u0026amp;mut S)-\u0026gt;Vec\u0026lt;u8\u0026gt;{source.next_token_unwrap().bytes().collect()}}pub enum Usize1{}impl Readable for Usize1{type Output=usize;fn read\u0026lt;R:BufRead,S:Source\u0026lt;R\u0026gt;\u0026gt;(source:\u0026amp;mut S)-\u0026gt;usize{usize::read(source).checked_sub(1).expect(\u0026#34;attempted to read the value 0 as a Usize1\u0026#34;)}}pub enum Isize1{}impl Readable for Isize1{type Output=isize;fn read\u0026lt;R:BufRead,S:Source\u0026lt;R\u0026gt;\u0026gt;(source:\u0026amp;mut S)-\u0026gt;isize{isize::read(source).checked_sub(1).unwrap_or_else(||{panic!(concat!(\u0026#34;attempted to read the value {} as a Isize1:\u0026#34;,\u0026#34; the value is isize::MIN and cannot be decremented\u0026#34;),std::isize::MIN,)})}}}pub mod source{use crate::__cargo_equip::preludes::proconio::*;use std::any::type_name;use std::fmt::Debug;use std::io::BufRead;use std::str::FromStr;pub mod line{use crate::__cargo_equip::preludes::proconio::*;use super::Source;use crate::__cargo_equip::crates::proconio::source::tokens::Tokens;use std::io::BufRead;pub struct LineSource\u0026lt;R:BufRead\u0026gt;{tokens:Tokens,reader:R,}impl\u0026lt;R:BufRead\u0026gt;LineSource\u0026lt;R\u0026gt;{pub fn new(reader:R)-\u0026gt;LineSource\u0026lt;R\u0026gt;{LineSource{tokens:\u0026#34;\u0026#34;.to_owned().into(),reader,}}fn prepare(\u0026amp;mut self){while self.tokens.is_empty(){let mut line=String::new();let num_bytes=self.reader.read_line(\u0026amp;mut line).expect(\u0026#34;failed to get linel maybe an IO error.\u0026#34;);if num_bytes==0{return;}self.tokens=line.into();}}}impl\u0026lt;R:BufRead\u0026gt;Source\u0026lt;R\u0026gt;for LineSource\u0026lt;R\u0026gt;{fn next_token(\u0026amp;mut self)-\u0026gt;Option\u0026lt;\u0026amp;str\u0026gt;{self.prepare();self.tokens.next_token()}fn is_empty(\u0026amp;mut self)-\u0026gt;bool{self.prepare();self.tokens.is_empty()}}use std::io::BufReader;impl\u0026lt;\u0026#39;a\u0026gt;From\u0026lt;\u0026amp;\u0026#39;a str\u0026gt;for LineSource\u0026lt;BufReader\u0026lt;\u0026amp;\u0026#39;a[u8]\u0026gt;\u0026gt;{fn from(s:\u0026amp;\u0026#39;a str)-\u0026gt;LineSource\u0026lt;BufReader\u0026lt;\u0026amp;\u0026#39;a[u8]\u0026gt;\u0026gt;{LineSource::new(BufReader::new(s.as_bytes()))}}}pub mod once{use crate::__cargo_equip::preludes::proconio::*;use super::Source;use crate::__cargo_equip::crates::proconio::source::tokens::Tokens;use std::io::BufRead;use std::marker::PhantomData;pub struct OnceSource\u0026lt;R:BufRead\u0026gt;{tokens:Tokens,_read:PhantomData\u0026lt;R\u0026gt;,}impl\u0026lt;R:BufRead\u0026gt;OnceSource\u0026lt;R\u0026gt;{pub fn new(mut source:R)-\u0026gt;OnceSource\u0026lt;R\u0026gt;{let mut context=String::new();source.read_to_string(\u0026amp;mut context).expect(\u0026#34;failed to read from source; maybe an IO error.\u0026#34;);OnceSource{tokens:context.into(),_read:PhantomData,}}}impl\u0026lt;R:BufRead\u0026gt;Source\u0026lt;R\u0026gt;for OnceSource\u0026lt;R\u0026gt;{fn next_token(\u0026amp;mut self)-\u0026gt;Option\u0026lt;\u0026amp;str\u0026gt;{self.tokens.next_token()}fn is_empty(\u0026amp;mut self)-\u0026gt;bool{self.tokens.is_empty()}}use std::io::BufReader;impl\u0026lt;\u0026#39;a\u0026gt;From\u0026lt;\u0026amp;\u0026#39;a str\u0026gt;for OnceSource\u0026lt;BufReader\u0026lt;\u0026amp;\u0026#39;a[u8]\u0026gt;\u0026gt;{fn from(s:\u0026amp;\u0026#39;a str)-\u0026gt;OnceSource\u0026lt;BufReader\u0026lt;\u0026amp;\u0026#39;a[u8]\u0026gt;\u0026gt;{OnceSource::new(BufReader::new(s.as_bytes()))}}}mod tokens{use crate::__cargo_equip::preludes::proconio::*;use std::{iter::Peekable,ptr::NonNull,str::SplitWhitespace};pub(super)struct Tokens{tokens:Peekable\u0026lt;SplitWhitespace\u0026lt;\u0026#39;static\u0026gt;\u0026gt;,_current_context:CurrentContext,}impl Tokens{pub(super)fn next_token(\u0026amp;mut self)-\u0026gt;Option\u0026lt;\u0026amp;str\u0026gt;{self.tokens.next()}pub(super)fn is_empty(\u0026amp;mut self)-\u0026gt;bool{self.tokens.peek().is_none()}}impl From\u0026lt;String\u0026gt;for Tokens{fn from(current_context:String)-\u0026gt;Self{let current_context=CurrentContext::from(current_context);unsafe{let tokens=current_context.0.as_ref().split_whitespace().peekable();Self{tokens,_current_context:current_context,}}}}unsafe impl Send for Tokens{}unsafe impl Sync for Tokens{}struct CurrentContext(NonNull\u0026lt;str\u0026gt;);impl From\u0026lt;String\u0026gt;for CurrentContext{fn from(s:String)-\u0026gt;Self{let s=s.into_boxed_str();Self(NonNull::new(Box::leak(s)).unwrap())}}impl Drop for CurrentContext{fn drop(\u0026amp;mut self){unsafe{Box::from_raw(self.0.as_mut())};}}}pub mod auto{use crate::__cargo_equip::preludes::proconio::*;#[cfg(debug_assertions)]pub use super::line::LineSource as AutoSource;#[cfg(not(debug_assertions))]pub use super::once::OnceSource as AutoSource;}pub trait Source\u0026lt;R:BufRead\u0026gt;{fn next_token(\u0026amp;mut self)-\u0026gt;Option\u0026lt;\u0026amp;str\u0026gt;;#[allow(clippy::wrong_self_convention)]fn is_empty(\u0026amp;mut self)-\u0026gt;bool;fn next_token_unwrap(\u0026amp;mut self)-\u0026gt;\u0026amp;str{self.next_token().expect(concat!(\u0026#34;failed to get the next token; \u0026#34;,\u0026#34;maybe reader reached an end of input. \u0026#34;,\u0026#34;ensure that arguments for `input!` macro is correctly \u0026#34;,\u0026#34;specified to match the problem input.\u0026#34;))}}impl\u0026lt;R:BufRead,S:Source\u0026lt;R\u0026gt;\u0026gt;Source\u0026lt;R\u0026gt;for\u0026amp;\u0026#39;_ mut S{fn next_token(\u0026amp;mut self)-\u0026gt;Option\u0026lt;\u0026amp;str\u0026gt;{(*self).next_token()}fn is_empty(\u0026amp;mut self)-\u0026gt;bool{(*self).is_empty()}}pub trait Readable{type Output;fn read\u0026lt;R:BufRead,S:Source\u0026lt;R\u0026gt;\u0026gt;(source:\u0026amp;mut S)-\u0026gt;Self::Output;}impl\u0026lt;T:FromStr\u0026gt;Readable for T where T::Err:Debug,{type Output=T;fn read\u0026lt;R:BufRead,S:Source\u0026lt;R\u0026gt;\u0026gt;(source:\u0026amp;mut S)-\u0026gt;T{let token=source.next_token_unwrap();match token.parse(){Ok(v)=\u0026gt;v,Err(e)=\u0026gt;panic!(concat!(\u0026#34;failed to parse the input `{input}` \u0026#34;,\u0026#34;to the value of type `{ty}`: {err:?}; \u0026#34;,\u0026#34;ensure that the input format is collectly specified \u0026#34;,\u0026#34;and that the input value must handle specified type.\u0026#34;,),input=token,ty=type_name::\u0026lt;T\u0026gt;(),err=e,),}}}}use crate::__cargo_equip::crates::proconio::source::{auto::AutoSource,line::LineSource};use std::io::{BufReader,Stdin};use std::sync::OnceLock;use std::{io::{self,BufRead},sync::Mutex,};pub use crate::__cargo_equip::crates::proconio::source::Readable as __Readable;pub enum StdinSource\u0026lt;R:BufRead\u0026gt;{Normal(AutoSource\u0026lt;R\u0026gt;),Interactive(LineSource\u0026lt;R\u0026gt;),Unknown(LineSource\u0026lt;R\u0026gt;),}impl\u0026lt;R:BufRead\u0026gt;source::Source\u0026lt;R\u0026gt;for StdinSource\u0026lt;R\u0026gt;{fn next_token(\u0026amp;mut self)-\u0026gt;Option\u0026lt;\u0026amp;str\u0026gt;{match self{StdinSource::Normal(source)=\u0026gt;source.next_token(),StdinSource::Interactive(source)=\u0026gt;source.next_token(),StdinSource::Unknown(source)=\u0026gt;source.next_token(),}}fn is_empty(\u0026amp;mut self)-\u0026gt;bool{match self{StdinSource::Normal(source)=\u0026gt;source.is_empty(),StdinSource::Interactive(source)=\u0026gt;source.is_empty(),StdinSource::Unknown(source)=\u0026gt;source.is_empty(),}}}pub static STDIN_SOURCE:OnceLock\u0026lt;Mutex\u0026lt;StdinSource\u0026lt;BufReader\u0026lt;Stdin\u0026gt;\u0026gt;\u0026gt;\u0026gt; =OnceLock::new();#[macro_export]macro_rules!__cargo_equip_macro_def_proconio_input{(@from[$source:expr]@rest)=\u0026gt;{};(@from[$source:expr]@rest mut$($rest:tt)*)=\u0026gt;{$crate::__cargo_equip::crates::proconio::input!{@from[$source]@mut[mut]@rest$($rest)*}};(@from[$source:expr]@rest$($rest:tt)*)=\u0026gt;{$crate::__cargo_equip::crates::proconio::input!{@from[$source]@mut[]@rest$($rest)*}};(@from[$source:expr]@mut[$($mut:tt)?]@rest$var:tt:$($rest:tt)*)=\u0026gt;{$crate::__cargo_equip::crates::proconio::input!{@from[$source]@mut[$($mut)*]@var$var@kind[]@rest$($rest)*}};(@from[$source:expr]@mut[$($mut:tt)?]@var$var:tt@kind[$($kind:tt)*]@rest)=\u0026gt;{let$($mut)*$var=$crate::__cargo_equip::crates::proconio::read_value!(@source[$source]@kind[$($kind)*]);};(@from[$source:expr]@mut[$($mut:tt)?]@var$var:tt@kind[$($kind:tt)*]@rest,$($rest:tt)*)=\u0026gt;{$crate::__cargo_equip::crates::proconio::input!(@from[$source]@mut[$($mut)*]@var$var@kind[$($kind)*]@rest);$crate::__cargo_equip::crates::proconio::input!(@from[$source]@rest$($rest)*);};(@from[$source:expr]@mut[$($mut:tt)?]@var$var:tt@kind[$($kind:tt)*]@rest$tt:tt$($rest:tt)*)=\u0026gt;{$crate::__cargo_equip::crates::proconio::input!(@from[$source]@mut[$($mut)*]@var$var@kind[$($kind)*$tt]@rest$($rest)*);};(from$source:expr,$($rest:tt)*)=\u0026gt;{#[allow(unused_variables,unused_mut)]let mut s=$source;$crate::__cargo_equip::crates::proconio::input!{@from[\u0026amp;mut s]@rest$($rest)*}};($($rest:tt)*)=\u0026gt;{let mut locked_stdin=$crate::__cargo_equip::crates::proconio::STDIN_SOURCE.get_or_init(||{std::sync::Mutex::new($crate::__cargo_equip::crates::proconio::StdinSource::Normal($crate::__cargo_equip::crates::proconio::source::auto::AutoSource::new(std::io::BufReader::new(std::io::stdin())),))}).lock().expect(concat!(\u0026#34;failed to lock the stdin; please re-run this program. \u0026#34;,\u0026#34;If this issue repeatedly occur, this is a bug in `proconio`. \u0026#34;,\u0026#34;Please report this issue from \u0026#34;,\u0026#34;\u0026lt;https://github.com/statiolake/proconio-rs/issues\u0026gt;.\u0026#34;));$crate::__cargo_equip::crates::proconio::input!{@from[\u0026amp;mut*locked_stdin]@rest$($rest)*}drop(locked_stdin);};}macro_rules!input{($($tt:tt)*)=\u0026gt;(crate::__cargo_equip_macro_def_proconio_input!{$($tt)*})}#[macro_export]macro_rules!__cargo_equip_macro_def_proconio_input_interactive{($($rest:tt)*)=\u0026gt;{let mut locked_stdin=$crate::__cargo_equip::crates::proconio::STDIN_SOURCE.get_or_init(||{std::sync::Mutex::new($crate::__cargo_equip::crates::proconio::StdinSource::Interactive($crate::__cargo_equip::crates::proconio::source::line::LineSource::new(std::io::BufReader::new(std::io::stdin())),))}).lock().expect(concat!(\u0026#34;failed to lock the stdin; please re-run this program. \u0026#34;,\u0026#34;If this issue repeatedly occur, this is a bug in `proconio`. \u0026#34;,\u0026#34;Please report this issue from \u0026#34;,\u0026#34;\u0026lt;https://github.com/statiolake/proconio-rs/issues\u0026gt;.\u0026#34;));$crate::__cargo_equip::crates::proconio::input!{from\u0026amp;mut*locked_stdin,$($rest)*}drop(locked_stdin);};}macro_rules!input_interactive{($($tt:tt)*)=\u0026gt;(crate::__cargo_equip_macro_def_proconio_input_interactive!{$($tt)*})}#[macro_export]macro_rules!__cargo_equip_macro_def_proconio_read_value{(@source[$source:expr]@kind[[$($kind:tt)*]])=\u0026gt;{$crate::__cargo_equip::crates::proconio::read_value!(@array@source[$source]@kind[]@rest$($kind)*)};(@array@source[$source:expr]@kind[$($kind:tt)*]@rest)=\u0026gt;{{let len=\u0026lt;usize as$crate::__cargo_equip::crates::proconio::__Readable\u0026gt;::read($source);$crate::__cargo_equip::crates::proconio::read_value!(@source[$source]@kind[[$($kind)*;len]])}};(@array@source[$source:expr]@kind[$($kind:tt)*]@rest;$($rest:tt)*)=\u0026gt;{$crate::__cargo_equip::crates::proconio::read_value!(@array@source[$source]@kind[$($kind)*]@len[$($rest)*])};(@array@source[$source:expr]@kind[$($kind:tt)*]@rest$tt:tt$($rest:tt)*)=\u0026gt;{$crate::__cargo_equip::crates::proconio::read_value!(@array@source[$source]@kind[$($kind)*$tt]@rest$($rest)*)};(@array@source[$source:expr]@kind[$($kind:tt)*]@len[$($len:tt)*])=\u0026gt;{{let len=$($len)*;(0..len).map(|_|$crate::__cargo_equip::crates::proconio::read_value!(@source[$source]@kind[$($kind)*])).collect::\u0026lt;Vec\u0026lt;_\u0026gt;\u0026gt;()}};(@source[$source:expr]@kind[($($kinds:tt)*)])=\u0026gt;{$crate::__cargo_equip::crates::proconio::read_value!(@tuple@source[$source]@kinds[]@current[]@rest$($kinds)*)};(@tuple@source[$source:expr]@kinds[$([$($kind:tt)*])*]@current[]@rest)=\u0026gt;{($($crate::__cargo_equip::crates::proconio::read_value!(@source[$source]@kind[$($kind)*]),)*)};(@tuple@source[$source:expr]@kinds[$($kinds:tt)*]@current[$($curr:tt)*]@rest)=\u0026gt;{$crate::__cargo_equip::crates::proconio::read_value!(@tuple@source[$source]@kinds[$($kinds)*[$($curr)*]]@current[]@rest)};(@tuple@source[$source:expr]@kinds[$($kinds:tt)*]@current[$($curr:tt)*]@rest,$($rest:tt)*)=\u0026gt;{$crate::__cargo_equip::crates::proconio::read_value!(@tuple@source[$source]@kinds[$($kinds)*[$($curr)*]]@current[]@rest$($rest)*)};(@tuple@source[$source:expr]@kinds[$($kinds:tt)*]@current[$($curr:tt)*]@rest$tt:tt$($rest:tt)*)=\u0026gt;{$crate::__cargo_equip::crates::proconio::read_value!(@tuple@source[$source]@kinds[$($kinds)*]@current[$($curr)*$tt]@rest$($rest)*)};(@source[$source:expr]@kind[])=\u0026gt;{compile_error!(concat!(\u0026#34;Reached unreachable statement while parsing macro input. \u0026#34;,\u0026#34;This is a bug in `proconio`. \u0026#34;,\u0026#34;Please report this issue from \u0026#34;,\u0026#34;\u0026lt;https://github.com/statiolake/proconio-rs/issues\u0026gt;.\u0026#34;));};(@source[$source:expr]@kind[$kind:ty])=\u0026gt;{\u0026lt;$kind as$crate::__cargo_equip::crates::proconio::__Readable\u0026gt;::read($source)}}macro_rules!read_value{($($tt:tt)*)=\u0026gt;(crate::__cargo_equip_macro_def_proconio_read_value!{$($tt)*})}pub fn is_stdin_empty()-\u0026gt;bool{use source::Source;let mut lock=STDIN_SOURCE.get_or_init(||{Mutex::new(StdinSource::Unknown(LineSource::new(BufReader::new(io::stdin(),))))}).lock().expect(concat!(\u0026#34;failed to lock the stdin; please re-run this program. \u0026#34;,\u0026#34;If this issue repeatedly occur, this is a bug in `proconio`. \u0026#34;,\u0026#34;Please report this issue from \u0026#34;,\u0026#34;\u0026lt;https://github.com/statiolake/proconio-rs/issues\u0026gt;.\u0026#34;));lock.is_empty()}} pub mod __proconio_derive_0_2_1 {pub use crate::__cargo_equip::macros::__proconio_derive_0_2_1::*;#[macro_export]macro_rules!__cargo_equip_macro_def___proconio_derive_0_2_1_derive_readable{($(_:tt)*)=\u0026gt;(::std::compile_error!(\u0026#34;`derive_readable` from `proconio-derive 0.2.1` should have been expanded\u0026#34;);)}#[macro_export]macro_rules!__cargo_equip_macro_def___proconio_derive_0_2_1_fastout{($(_:tt)*)=\u0026gt;(::std::compile_error!(\u0026#34;`fastout` from `proconio-derive 0.2.1` should have been expanded\u0026#34;);)}} } pub(crate) mod macros { pub mod __algo_0_1_0 {pub use crate::{__cargo_equip_macro_def___algo_0_1_0_maxim as maxim,__cargo_equip_macro_def___algo_0_1_0_minim as minim,__cargo_equip_macro_def___algo_0_1_0_println_iter as println_iter};} pub mod codeforces {} pub mod proconio {pub use crate::{__cargo_equip_macro_def_proconio_input as input,__cargo_equip_macro_def_proconio_input_interactive as input_interactive,__cargo_equip_macro_def_proconio_read_value as read_value};} pub mod __proconio_derive_0_2_1 {pub use crate::{__cargo_equip_macro_def___proconio_derive_0_2_1_derive_readable as derive_readable,__cargo_equip_macro_def___proconio_derive_0_2_1_fastout as fastout};} } pub(crate) mod prelude {pub use crate::__cargo_equip::crates::*;} mod preludes { pub mod __algo_0_1_0 {} pub mod codeforces {pub(in crate::__cargo_equip)use crate::__cargo_equip::crates::{__algo_0_1_0 as algo,proconio};} pub mod proconio {pub(in crate::__cargo_equip)use crate::__cargo_equip::crates::__proconio_derive_0_2_1 as proconio_derive;} pub mod __proconio_derive_0_2_1 {} } } ","date":"Feb 5, 2026","externalUrl":null,"permalink":"/en/codeforces/template/","section":"Codeforces","summary":"","title":"A Practical Rust Template for Codeforces","type":"codeforces"},{"content":"English translations of contest write-ups and reusable competitive-programming templates.\n","date":"Feb 5, 2026","externalUrl":null,"permalink":"/en/codeforces/","section":"Codeforces","summary":"","title":"Codeforces","type":"codeforces"},{"content":"","date":"Feb 5, 2026","externalUrl":null,"permalink":"/en/tags/codeforces/","section":"Tags","summary":"","title":"Codeforces","type":"tags"},{"content":"","date":"Feb 5, 2026","externalUrl":null,"permalink":"/en/categories/competitive-programming/","section":"Categories","summary":"","title":"Competitive Programming","type":"categories"},{"content":"","date":"Feb 4, 2026","externalUrl":null,"permalink":"/en/tags/algorithm/","section":"Tags","summary":"","title":"Algorithm","type":"tags"},{"content":"","date":"Feb 4, 2026","externalUrl":null,"permalink":"/en/categories/algorithms/","section":"Categories","summary":"","title":"Algorithms","type":"categories"},{"content":"","date":"Feb 4, 2026","externalUrl":null,"permalink":"/en/tags/leetcode/","section":"Tags","summary":"","title":"LeetCode","type":"tags"},{"content":"This is the solution write-up for today\u0026rsquo;s LeetCode Daily Challenge.\n","date":"Feb 4, 2026","externalUrl":null,"permalink":"/en/leetcode/2026/02/04/example/","section":"LeetCode Solutions","summary":"","title":"LeetCode Daily Challenge: Example","type":"leetcode"},{"content":"English translations of the active LeetCode solutions, including explanations, code, formulas, and examples. Archived notes are intentionally omitted.\n","date":"Feb 4, 2026","externalUrl":null,"permalink":"/en/leetcode/","section":"LeetCode Solutions","summary":"","title":"LeetCode Solutions","type":"leetcode"},{"content":"","date":"Dec 25, 2024","externalUrl":null,"permalink":"/en/ctf/forensics/","section":"CTF Notes","summary":"","title":"File Forensics","type":"ctf"},{"content":"","date":"Dec 25, 2024","externalUrl":null,"permalink":"/en/tags/file-forensics/","section":"Tags","summary":"","title":"File Forensics","type":"tags"},{"content":"","date":"Dec 25, 2024","externalUrl":null,"permalink":"/en/tags/png/","section":"Tags","summary":"","title":"PNG","type":"tags"},{"content":" PNG CRC32 Repair Tool # This is a tool for repairing PNG image CRC32 checksums, primarily by adjusting the image width and height.\nFeatures # CRC32 Detection\nAutomatically detect the CRC32 value of a PNG file\u0026rsquo;s IHDR chunk Compare the actual CRC32 with the expected value Automatic Repair\nSupports three repair modes: Repair the height only Repair the width only Repair both the height and width Automatically generate a repaired file with the _fix.png suffix Visual Output\nUse colored output to show the processing steps Display the current and repaired image dimensions Display detailed CRC32 information Usage # python break.py \u0026lt;png_file_path\u0026gt; For example:\npython break.py test.png Output Legend # Green: success information Red: error information Yellow: expected values Cyan: informational messages Technical Details # IHDR Class\nProcess the IHDR chunk of a PNG file Provide methods for reading and modifying the width and height Calculate the CRC32 checksum Repair Strategy\nFirst try changing only the height (fastest) Then try changing only the width Finally try changing both the width and height (slowest) File Processing\nSupport binary file reading and writing Automatically back up the original file Handle errors and exceptions Notes # The input file must be a valid PNG file. The tool creates the repaired file in the same directory as the original file. The repair process may take some time, especially when trying to repair both the width and height. # -*- coding: utf-8 -*- import binascii import struct import sys from pathlib import Path from typing import Optional, Tuple # ANSI escape codes for colors class Colors: RED = \u0026#34;\\033[91m\u0026#34; GREEN = \u0026#34;\\033[92m\u0026#34; YELLOW = \u0026#34;\\033[93m\u0026#34; BLUE = \u0026#34;\\033[94m\u0026#34; CYAN = \u0026#34;\\033[96m\u0026#34; RESET = \u0026#34;\\033[0m\u0026#34; class IHDR: def __init__(self, data: bytes): self.raw_data = data self._header = data[:4] # IHDR chunk type self._height_bytes = data[8:12] self._width_bytes = data[4:8] self._ends = data[12:] # bit depth, color type, etc @property def width(self) -\u0026gt; int: return int.from_bytes(self._width_bytes, \u0026#34;big\u0026#34;) @property def height(self) -\u0026gt; int: return int.from_bytes(self._height_bytes, \u0026#34;big\u0026#34;) def get_data(self, width=None, height=None) -\u0026gt; bytes: return ( bytes(self._header) + (bytes(self._width_bytes) if width is None else struct.pack(\u0026#34;\u0026gt;i\u0026#34;, width)) + ( bytes(self._height_bytes) if height is None else struct.pack(\u0026#34;\u0026gt;i\u0026#34;, height) ) + bytes(self._ends) ) def crc32(self, width=None, height=None) -\u0026gt; int: return binascii.crc32(self.get_data(width, height)) \u0026amp; 0xFFFFFFFF @staticmethod def from_png(png_data: bytes) -\u0026gt; Tuple[\u0026#34;IHDR\u0026#34;, int]: \u0026#34;\u0026#34;\u0026#34;Extract IHDR from PNG file data and return (IHDR, expected_crc32)\u0026#34;\u0026#34;\u0026#34; ihdr_data = png_data[12:29] expected_crc32 = int.from_bytes(png_data[29:33], \u0026#34;big\u0026#34;) return IHDR(ihdr_data), expected_crc32 def try_fix_height(ihdr: IHDR, expected_crc32: int) -\u0026gt; Optional[int]: for height in range(0, 65535): if ihdr.crc32(height=height) == expected_crc32: return height return None def try_fix_width(ihdr: IHDR, expected_crc32: int) -\u0026gt; Optional[int]: for width in range(0, 65535): if ihdr.crc32(width=width) == expected_crc32: return width return None def try_fix_both( ihdr: IHDR, expected_crc32: int ) -\u0026gt; Tuple[Optional[int], Optional[int]]: for height in range(0, 65535): for width in range(0, 65535): if ihdr.crc32(width=width, height=height) == expected_crc32: return height, width return None, None def save_fixed_png( original_data: bytes, width: Optional[int] = None, height: Optional[int] = None, output_path: Path | None = None, ) -\u0026gt; None: \u0026#34;\u0026#34;\u0026#34;Save a new PNG with fixed dimensions\u0026#34;\u0026#34;\u0026#34; if output_path is None: output_path = Path(str(png_path).replace(\u0026#34;.png\u0026#34;, \u0026#34;_fix.png\u0026#34;)) # Only modify if we have new dimensions if width is None and height is None: return # Copy original data new_data = bytearray(original_data) # Update width if provided (at offset 16) if width is not None: new_data[16:20] = struct.pack(\u0026#34;\u0026gt;i\u0026#34;, width) # Update height if provided (at offset 20) if height is not None: new_data[20:24] = struct.pack(\u0026#34;\u0026gt;i\u0026#34;, height) # Calculate new CRC32 for IHDR chunk new_crc = binascii.crc32(new_data[12:29]) \u0026amp; 0xFFFFFFFF new_data[29:33] = struct.pack(\u0026#34;\u0026gt;I\u0026#34;, new_crc) # Save new file with open(output_path, \u0026#34;wb\u0026#34;) as f: f.write(new_data) print(f\u0026#34;{Colors.GREEN}Saved fixed PNG to: {output_path}{Colors.RESET}\u0026#34;) def try_fix_crc32(img_data: bytes, png_path: Path) -\u0026gt; None: ihdr, expected_crc32 = IHDR.from_png(img_data) real_crc32 = ihdr.crc32() if expected_crc32 == real_crc32: print(f\u0026#34;{Colors.GREEN}CRC32 is correct!{Colors.RESET}\u0026#34;) return print(f\u0026#34;{Colors.CYAN}IHDR data:{Colors.RESET} {ihdr.get_data()}\u0026#34;) print(f\u0026#34;{Colors.YELLOW}Expected CRC32: 0x{expected_crc32:X}\u0026#34;) print(f\u0026#34;{Colors.RED}Current CRC32: 0x{real_crc32:X}{Colors.RESET}\u0026#34;) print(f\u0026#34;{Colors.CYAN}Current dimensions: {ihdr.width}x{ihdr.height}{Colors.RESET}\u0026#34;) # Try fixing height height = try_fix_height(ihdr, expected_crc32) if height is not None: print(f\u0026#34;{Colors.GREEN}Found height fix: {height} (0x{height:X})\u0026#34;) print(f\u0026#34;Real dimensions: {ihdr.width}x{height}{Colors.RESET}\u0026#34;) save_fixed_png( img_data, height=height, output_path=png_path.parent / f\u0026#34;{png_path.stem}_fix.png\u0026#34;, ) return # Try fixing width width = try_fix_width(ihdr, expected_crc32) if width is not None: print(f\u0026#34;{Colors.GREEN}Found width fix: {width} (0x{width:X})\u0026#34;) print(f\u0026#34;Real dimensions: {width}x{ihdr.height}{Colors.RESET}\u0026#34;) save_fixed_png( img_data, width=width, output_path=png_path.parent / f\u0026#34;{png_path.stem}_fix.png\u0026#34;, ) return # Try fixing both height, width = try_fix_both(ihdr, expected_crc32) if height is not None and width is not None: print( f\u0026#34;{Colors.GREEN}Found height/width fix: {height}x{width} (0x{height:X}x0x{width:X}){Colors.RESET}\u0026#34; ) save_fixed_png( img_data, width=width, height=height, output_path=png_path.parent / f\u0026#34;{png_path.stem}_fix.png\u0026#34;, ) return print(f\u0026#34;{Colors.RED}No fix found{Colors.RESET}\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: if len(sys.argv) != 2: print(f\u0026#34;{Colors.RED}Usage: python {sys.argv[0]} \u0026lt;png_file_path\u0026gt;{Colors.RESET}\u0026#34;) sys.exit(1) png_path = Path(sys.argv[1]) if not png_path.exists(): print(f\u0026#34;{Colors.RED}Error: File {png_path} does not exist{Colors.RESET}\u0026#34;) sys.exit(1) if not png_path.is_file(): print(f\u0026#34;{Colors.RED}Error: {png_path} is not a file{Colors.RESET}\u0026#34;) sys.exit(1) try: with open(png_path, \u0026#34;rb\u0026#34;) as f: img_data = f.read() try_fix_crc32(img_data, png_path) except Exception as e: print(f\u0026#34;{Colors.RED}Error: {str(e)}{Colors.RESET}\u0026#34;) sys.exit(1) f ","date":"Dec 25, 2024","externalUrl":null,"permalink":"/en/ctf/forensics/png_width_height/","section":"CTF Notes","summary":"","title":"Repairing PNG Dimensions with CRC32","type":"ctf"},{"content":" Problem A # fn solve() { input! { n: usz, a: [usz; n] } let mut cur = 0; for i in 0..n { cur += 1; if a[i] == cur { cur += 1; } } println!(\u0026#34;{}\u0026#34;, cur); } fn main() { input! { t: usize } for _ in 0..t { solve(); } } Problem B # For each possible element, greedily find the maximum union of all remaining sets when that element is absent.\nfn solve() { input! { n: usize, } let mut mask_k = vec![]; let mut hm = HashMap::new(); let mut cnt: u64 = 0; for _ in 0..n { input! { x: usize, p: [usize; x] } let mut mask = 0; for item in p { if !hm.contains_key(\u0026amp;item) { hm.insert(item, cnt); cnt += 1; } mask |= 1 \u0026lt;\u0026lt; hm[\u0026amp;item]; } mask_k.push(mask); } let mut res = 0; for i in 0..cnt { let mut cur: u64 = 0; for \u0026amp;mask in \u0026amp;mask_k { if ((mask \u0026gt;\u0026gt; i) \u0026amp; 1) == 0 { cur |= mask; } } res = res.max(cur.count_ones()); } println!(\u0026#34;{}\u0026#34;, res); } fn main() { input! { t: usize } for _ in 0..t { solve(); } } Problem C # fn solve() { input! { n: usize, cards: [i64; n] } // 0 select odd // 1 skip odd // 2 select even // 3 skip even let (mut a,mut b,mut c) = (cards[0], cards[0].max(0), i64::MIN); for i in 1..n { let na = a.max(c) + cards[i]; let nb = a.max(c) + cards[i].max(0); let nc = b.max(c); a = na; b = nb; c = nc; } println!(\u0026#34;{}\u0026#34;, a.max(b).max(c)); } fn main() { input! { t: usize } dbg!(t); for _ in 0..t { solve(); } } Problem D # #include \u0026lt;bits/stdc++.h\u0026gt; using namespace std; using ll = long long; const int maxn = 200004; int n; struct Node { ll size, val, dp1, dp2; }; map\u0026lt;Node *, vector\u0026lt;Node *\u0026gt;\u0026gt; e; Node ns[maxn]; void dfs1(Node *u, Node *f) { u-\u0026gt;size = 1; for (auto v: e[u]) { if (v != f) { dfs1(v, u); u-\u0026gt;size += v-\u0026gt;size; u-\u0026gt;dp1 += v-\u0026gt;dp1 + v-\u0026gt;size * (u-\u0026gt;val ^ v-\u0026gt;val); } } } void dfs2(Node *u, Node *f) { for (auto \u0026amp;v: e[u]) { if (v != f) { ll w = u-\u0026gt;dp2 + u-\u0026gt;dp1 - v-\u0026gt;dp1 - v-\u0026gt;size * (u-\u0026gt;val ^ v-\u0026gt;val); v-\u0026gt;dp2 = w + (n - v-\u0026gt;size) * (u-\u0026gt;val ^ v-\u0026gt;val); dfs2(v, u); } } } void solve() { cin \u0026gt;\u0026gt; n; e.clear(); for (int i = 1; i \u0026lt;= n; i++) { cin \u0026gt;\u0026gt; ns[i].val; ns[i].dp1 = ns[i].dp2 = ns[i].size = 0; } for (int i = 1; i \u0026lt; n; i++) { int u, v; cin \u0026gt;\u0026gt; u \u0026gt;\u0026gt; v; e[ns + u].push_back(ns + v); e[ns + v].push_back(ns + u); } dfs1(ns + 1, nullptr); dfs2(ns + 1, nullptr); for (int i = 1; i \u0026lt;= n; i++) { printf(\u0026#34;%lld \u0026#34;, ns[i].dp1 + ns[i].dp2); } putchar(\u0026#39;\\n\u0026#39;); } int main() { cin.tie(0)-\u0026gt;sync_with_stdio(0); int T; cin \u0026gt;\u0026gt; T; while (T--) { solve(); } } ","date":"Sep 25, 2023","externalUrl":null,"permalink":"/en/codeforces/1882/","section":"Codeforces","summary":"","title":"Codeforces Round 899 (Div. 2) - ID 1882","type":"codeforces"},{"content":"","date":"Jan 13, 2023","externalUrl":null,"permalink":"/en/tags/zip/","section":"Tags","summary":"","title":"ZIP","type":"tags"},{"content":"Reference\nLocal file header (04 03 4B 50) Central directory file header (02 01 4B 50) End-of-central-directory record (06 05 4B 50) ","date":"Jan 13, 2023","externalUrl":null,"permalink":"/en/ctf/forensics/zip/","section":"CTF Notes","summary":"","title":"ZIP File Format Notes","type":"ctf"},{"content":"No additional notes are currently recorded for this PNG format entry.\n","date":"Jan 12, 2023","externalUrl":null,"permalink":"/en/ctf/forensics/png/","section":"CTF Notes","summary":"","title":"PNG File Format Notes","type":"ctf"},{"content":"","date":"Jan 11, 2023","externalUrl":null,"permalink":"/en/tags/file-format/","section":"Tags","summary":"","title":"File Format","type":"tags"},{"content":"No additional notes are currently recorded for this JPEG format entry.\n","date":"Jan 11, 2023","externalUrl":null,"permalink":"/en/ctf/forensics/jpg/","section":"CTF Notes","summary":"","title":"JPEG File Format Notes","type":"ctf"},{"content":"","date":"Jan 10, 2023","externalUrl":null,"permalink":"/en/tags/bmp/","section":"Tags","summary":"","title":"BMP","type":"tags"},{"content":" Fields You May Need to Modify # struct BITMAPFILEHEADER bmfh \u0026gt; DWORD bfOffBits, whose default value is 54 struct BITMAPINFOHEADER bmih \u0026gt; DOWRD biSize, whose default value is 40 ","date":"Jan 10, 2023","externalUrl":null,"permalink":"/en/ctf/forensics/bmp/","section":"CTF Notes","summary":"","title":"BMP File Format Notes","type":"ctf"},{"content":"","date":"Jun 11, 2022","externalUrl":null,"permalink":"/en/tags/greedy/","section":"Tags","summary":"","title":"Greedy","type":"tags"},{"content":"The original article is available at https://home.dawnmagnet.date/leetcode/2022/06/11/.\nA binary string is monotone increasing if it consists of some number of 0s (possibly none) followed by some number of 1s (possibly none).\nGiven a binary string s, you may flip any 0 to 1 or any 1 to 0.\nReturn the minimum number of flips needed to make s monotone increasing.\nExample 1:\n**Input:** s = \u0026quot;00110\u0026quot; **Output:** 1 **Explanation:** Flip the last character to obtain 00111. Example 2:\n**Input:** s = \u0026quot;010110\u0026quot; **Output:** 2 **Explanation:** Flip characters to obtain 011111 or 000111. Example 3:\n**Input:** s = \u0026quot;00011000\u0026quot; **Output:** 2 **Explanation:** Flip characters to obtain 00000000. Constraints:\n1 \u0026lt;= s.length \u0026lt;= 105 s[i] is either \u0026lsquo;0\u0026rsquo; or \u0026lsquo;1\u0026rsquo;. Source: LeetCode Link: https://leetcode.cn/problems/flip-string-to-monotone-increasing Copyright belongs to LeetCode. For commercial use, contact the official copyright holder; for non-commercial use, cite the source as required.\nAnalysis - 1 # The key difficulty is minimizing the number of flips. Choose one exact position in the string as the boundary between 0 and 1. Once the boundary is fixed, turn every 1 before it into 0 and every 0 after it into 1; the total number of flips can then be calculated directly.\nThe remaining question is how to quickly count the 1s before a given boundary and the 0s after it. A dynamic-programming approach is natural: use two arrays and traverse the string from both directions to obtain these counts for every position. Then make one more pass, add the two counts for each possible boundary, and take the minimum cost.\nC++ Code - 1 # class Solution { public: int minFlipsMonoIncr(string s) { int n = s.size(); vector\u0026lt;int\u0026gt; v1(n + 1), v2(n + 1); for (int i = 0; i \u0026lt; n; ++i) v1[i + 1] = v1[i] + (s[i] == \u0026#39;1\u0026#39;); for (int i = n - 1; i \u0026gt;= 0; --i) v2[i] = v2[i + 1] + (s[i] == \u0026#39;0\u0026#39;); int res = n; for (int i = 0; i \u0026lt;= n; ++i) res = min(res, v1[i] + v2[i]); return res; } }; Analysis 2 # The previous approach can be optimized because it uses two full arrays. We can solve the problem in O(1) extra space with another dynamic-programming formulation.\nSuppose a string has minimum flip count n. If we append one character, can we compute the minimum flip count for the new string?\nIf the appended character is 1, either 0 or 1 may precede it, so no additional flip is needed.\nIf the appended character is 0, it must be preceded by 0, so again no additional flip is needed for that valid state.\nBecause the last character of the previous string affects the possible state after each flip, we must consider the two ending characters separately.\nLet dp[i][j] be a dynamic-programming array whose value is the minimum number of flips for the substring s[0:i] when its final character after flipping is j (where j is 0 or 1).\nThe following transitions handle the case where the appended character is not flipped:\nIf the appended character is 0, then dp[i][0]=dp[i-1][0]. If the appended character is 1, then dp[i][1]=min(dp[i-1][0], dp[i-1][1]). If the appended character itself must be flipped, add one flip:\nIf the appended character is 0, then dp[i][1]=min(dp[i-1][0], dp[i-1][1])+1. If the appended character is 1, then dp[i][0]=dp[i-1][0]+1. Together, these form a consistent dynamic-programming recurrence.\nC++ Code - 2 # class Solution { public: int minFlipsMonoIncr(string s) { int a = 0, b = 0; for (auto \u0026amp; ch : s) { b = min(a, b); if (ch == \u0026#39;1\u0026#39;) a++; else b++; } return min(a, b); } }; ","date":"Jun 11, 2022","externalUrl":null,"permalink":"/en/leetcode/2022/06/11/","section":"LeetCode Solutions","summary":"","title":"LeetCode 926: Flip String to Monotone Increasing","type":"leetcode"},{"content":"","date":"Jan 19, 2022","externalUrl":null,"permalink":"/en/tags/hash-table/","section":"Tags","summary":"","title":"Hash Table","type":"tags"},{"content":"The original article is available at https://home.dawnmagnet.date/leetcode/2022/01/19/.\nGiven an integer array nums and an integer k, determine whether there are two distinct indices i and j such that nums[i] == nums[j] and abs(i - j) \u0026lt;= k. Return true if such a pair exists; otherwise, return false.\nExample 1:\n**Input:** nums = [1,2,3,1], k = 3 **Output:** true Example 2:\n**Input:** nums = [1,0,1,1], k = 1 **Output:** true Example 3:\n**Input:** nums = [1,2,3,1,2,3], k = 2 **Output:** false Constraints:\n1 \u0026lt;= nums.length \u0026lt;= 10^5 -10^9 \u0026lt;= nums[i] \u0026lt;= 10^9 0 \u0026lt;= k \u0026lt;= 10^5 Source: LeetCode Link: https://leetcode-cn.com/problems/contains-duplicate-ii Copyright belongs to LeetCode. For commercial use, contact the official copyright holder; for non-commercial use, cite the source as required.\nAnalysis # In plain terms, this problem asks us to find two equal values in an array whose indices are no more than a given distance apart. How can we check this efficiently?\nA sliding window solves the problem efficiently. By the problem\u0026rsquo;s condition, any possible pair must lie within an index range of length k+1. We can maintain a sliding window of length k+1 and use a hash table to detect duplicates, checking for a valid answer only inside that window.\nRust Code # impl Solution { pub fn contains_nearby_duplicate(mut nums: Vec\u0026lt;i32\u0026gt;, k: i32) -\u0026gt; bool { let k = k as usize; let mut map = std::collections::HashMap::new(); for i in 0..nums.len() { if i \u0026gt; k { *map.entry(nums[i - k - 1]).or_insert(0) -= 1; } *map.entry(nums[i]).or_insert(0) += 1; if *map.entry(nums[i]).or_insert(0) \u0026gt; 1 { return true; } } return false; } } ","date":"Jan 19, 2022","externalUrl":null,"permalink":"/en/leetcode/2022/01/19/","section":"LeetCode Solutions","summary":"","title":"LeetCode 219: Contains Duplicate II","type":"leetcode"},{"content":"The original article is available at https://home.dawnmagnet.date/leetcode/2022/01/18/.\nGiven a list of times in 24-hour format (\u0026quot;HH:MM\u0026quot;), find the minimum difference between any two times in the list, expressed in minutes.\nExample 1:\n**Input:** timePoints = [\u0026quot;23:59\u0026quot;,\u0026quot;00:00\u0026quot;] **Output:** 1 Example 2:\n**Input:** timePoints = [\u0026quot;00:00\u0026quot;,\u0026quot;23:59\u0026quot;,\u0026quot;00:00\u0026quot;] **Output:** 0 Constraints:\n2 \u0026lt;= timePoints \u0026lt;= 2 * 104 timePoints[i] has the format \u0026quot;HH:MM\u0026quot;. Source: LeetCode Link: https://leetcode-cn.com/problems/minimum-time-difference Copyright belongs to LeetCode. For commercial use, contact the official copyright holder; for non-commercial use, cite the source as required.\nAnalysis # First, convert each time into its corresponding number of minutes. Mark that minute in a Boolean array of length 1440 (24*60), then enumerate the occupied positions. Sorting the times would also work, but the domain is so small (only 1440 minutes) that sorting is unnecessary.\nAfter placing the times in the array, there are two kinds of gaps to consider: the gap between two consecutive occupied positions, and the wraparound gap between the first and last occupied positions. The latter needs special attention when computing the answer.\nRust Code # pub fn parse(s: \u0026amp;str) -\u0026gt; usize { let mut res = 0; let b: Vec\u0026lt;usize\u0026gt; = s.as_bytes().iter().map(|\u0026amp;x| x as usize - 48).collect(); (b[0] * 10 + b[1]) * 60 + b[3] * 10 + b[4] } impl Solution { pub fn find_min_difference(time_points: Vec\u0026lt;String\u0026gt;) -\u0026gt; i32 { let mut c = [false; 1440]; for item in \u0026amp;time_points { let pos = parse(item); if c[pos] { return 0; } else { c[parse(item)] = true; } } let mut cur = usize::MAX; let mut res = 10000; let mut first = 0; for time in 0..1440 { if c[time] { if cur == usize::MAX { cur = time; first = time + 1440; } else { res = res.min(time - cur); cur = time; } } } res = res.min(first - cur); res as i32 } } ","date":"Jan 18, 2022","externalUrl":null,"permalink":"/en/leetcode/2022/01/18/","section":"LeetCode Solutions","summary":"","title":"LeetCode 539: Minimum Time Difference","type":"leetcode"},{"content":"","date":"Jan 18, 2022","externalUrl":null,"permalink":"/en/tags/sorting/","section":"Tags","summary":"","title":"Sorting","type":"tags"},{"content":"","date":"Jan 17, 2022","externalUrl":null,"permalink":"/en/tags/dynamic-programming/","section":"Tags","summary":"","title":"Dynamic Programming","type":"tags"},{"content":"The original article is available at https://home.dawnmagnet.date/leetcode/2022/01/17/.\nGiven an integer n, count how many strings of length n can be formed according to these rules:\nEvery character in the string must be a lowercase vowel ('a', 'e', 'i', 'o', 'u').\nEvery 'a' must be followed by an 'e'. Every 'e' must be followed by an 'a' or an 'i'. An 'i' cannot be followed by another 'i'. Every 'o' must be followed by an 'i' or a 'u'. Every 'u' must be followed by an 'a'. Because the answer may be large, return it modulo 10^9 + 7.\nExample 1:\n**Input:** n = 1 **Output:** 5 **Explanation:** The possible strings are \u0026quot;a\u0026quot;, \u0026quot;e\u0026quot;, \u0026quot;i\u0026quot;, \u0026quot;o\u0026quot;, and \u0026quot;u\u0026quot;. Example 2:\n**Input:** n = 2 **Output:** 10 **Explanation:** The possible strings are \u0026quot;ae\u0026quot;, \u0026quot;ea\u0026quot;, \u0026quot;ei\u0026quot;, \u0026quot;ia\u0026quot;, \u0026quot;ie\u0026quot;, \u0026quot;io\u0026quot;, \u0026quot;iu\u0026quot;, \u0026quot;oi\u0026quot;, \u0026quot;ou\u0026quot;, and \u0026quot;ua\u0026quot;. Example 3:\n**Input:** n = 5 **Output:** 68 Constraints:\n1 \u0026lt;= n \u0026lt;= 2 * 10^4 Source: LeetCode Link: https://leetcode-cn.com/problems/count-vowels-permutation Copyright belongs to LeetCode. For commercial use, contact the official copyright holder; for non-commercial use, cite the source as required.\nAnalysis # This problem is mainly about recognizing a pattern. More formally, it can be solved with dynamic programming, but the recurrence is quite simple.\nFrom the rules, we can see that the possible extensions of a vowel sequence depend only on its final character. We do not need to know the entire prefix; knowing its last character is enough to extend it. Therefore, a single array can store the number of sequences ending in each of a, e, i, o, and u, which greatly simplifies the computation.\nBy deriving the transitions from the conditions, we obtain:\na can be preceded by e, i, or u. e can be preceded by a or i. i can be preceded by e or o. o can be preceded by i. u can be preceded by i or o. These transitions give the recurrence. Once we compute the number of sequences ending in each of a, e, i, o, and u for the requested length, add them to obtain the answer.\nRust Code # const m: i64 = 1_000_000_007; impl Solution { pub fn count_vowel_permutation(n: i32) -\u0026gt; i32 { let mut c = [1i64, 1, 1, 1, 1]; for i in 1..n { c = [ (c[1] + c[2] + c[4]) % m, (c[0] + c[2]) % m, (c[1] + c[3]) % m, c[2], (c[2] + c[3]) % m, ]; } (c.iter().sum::\u0026lt;i64\u0026gt;() % m) as i32 } } ","date":"Jan 17, 2022","externalUrl":null,"permalink":"/en/leetcode/2022/01/17/","section":"LeetCode Solutions","summary":"","title":"LeetCode 1220: Count Vowels Permutation","type":"leetcode"},{"content":" The original article is available at https://home.dawnmagnet.date/leetcode/2022/01/16/.\nGiven a singly linked list, randomly select one of its nodes and return the selected node\u0026rsquo;s value. Every node must have the same probability of being selected.\nImplement the Solution class:\nSolution(ListNode head) initializes the object with an integer array. int getRandom() randomly selects a node from the linked list and returns its value. Every node in the list must have an equal probability of being selected. Example:\nInput [\u0026quot;Solution\u0026quot;, \u0026quot;getRandom\u0026quot;, \u0026quot;getRandom\u0026quot;, \u0026quot;getRandom\u0026quot;, \u0026quot;getRandom\u0026quot;, \u0026quot;getRandom\u0026quot;] [[[1, 2, 3]], [], [], [], [], []] Output [null, 1, 3, 2, 2, 3] Explanation Solution solution = new Solution([1, 2, 3]); solution.getRandom(); // returns 1 solution.getRandom(); // returns 3 solution.getRandom(); // returns 2 solution.getRandom(); // returns 2 solution.getRandom(); // returns 3 // The getRandom() method should randomly return one of 1, 2, and 3, with equal probability for each element. Constraints:\nThe number of nodes in the linked list is in the range [1, \\(10^4\\)]. \\(-10^4\\) \u0026lt;= Node.val \u0026lt;= \\(10^4\\) getRandom is called at most \\(10^4\\) times. Follow-up:\nHow should this be handled if the linked list is very large and its length is unknown? Can you solve the problem without using extra space? Source: LeetCode Link: https://leetcode-cn.com/problems/linked-list-random-node Copyright belongs to LeetCode. For commercial use, contact the official copyright holder; for non-commercial use, cite the source as required.\nAnalysis # Problems like this often look simple and are easy to solve at a basic level, but satisfying every follow-up requirement is much more challenging.\nRather than viewing the input as an ordinary linked list, it is more useful to view it as a data stream of unknown length. The real challenge is to sample a random value from a stream whose length is unknown, as the follow-up makes clear, while also using constant extra space. If the stream is very long but the algorithm needs more than constant space, such as \\(O(n)\\), the algorithm would be impractical.\nThis is where the reservoir sampling algorithm is useful. It is completely normal not to know it at first; after seeing it a few times, the idea becomes familiar.\nRemember one thing: reservoir sampling is used to obtain a random value from a data stream of unknown length.\nSuppose we have processed \\(n\\) numbers and selected one of the first \\(n\\) numbers uniformly at random. Each number has probability \\(\\frac1n\\) of being selected. If we add a new number, the \\((n+1)\\)-th number, we want every number to have probability \\(\\frac1{n+1}\\), including the new number.\nHow can we make this change in probability? Ensure that the \\((n+1)\\)-th number is selected with probability \\(\\frac1{n+1}\\). Once that is true, each of the first \\(n\\) numbers was previously selected with equal probability, so retaining the previous result with probability \\(\\frac n{n+1}\\) makes the probability of each old number \\(\\frac1{n+1}\\) as well.\nThis is a brief explanation and proof of reservoir sampling. Consult additional references if you would like a more detailed treatment.\nThe algorithm is now clear. For the \\(n\\)-th number, generate a random number. If the generated choice selects the current number with probability \\(\\frac1n\\), replace the result with the \\(n\\)-th number; otherwise leave the result unchanged and continue through the stream.\nOn the LeetCode platform, Rust supports a third-party random-number library named rand. Its documentation is available at https://docs.rs/rand/latest/rand/.\nRust Code # use rand::prelude::*; struct Solution { node: Option\u0026lt;Box\u0026lt;ListNode\u0026gt;\u0026gt; } impl Solution { fn new(head: Option\u0026lt;Box\u0026lt;ListNode\u0026gt;\u0026gt;) -\u0026gt; Self { Solution { node: head } } fn get_random(\u0026amp;self) -\u0026gt; i32 { let mut node = self.node.clone(); let mut res = 0; let mut factor = 1; let mut rng = rand::thread_rng(); while let Some(node_some) = node { let rnd: i32 = rng.gen(); if rnd % factor == 0 { res = node_some.val; } factor += 1; node = node_some.next; } res } } ","date":"Jan 16, 2022","externalUrl":null,"permalink":"/en/leetcode/2022/01/16/","section":"LeetCode Solutions","summary":"","title":"LeetCode 382: Linked List Random Node","type":"leetcode"},{"content":"","date":"Jan 16, 2022","externalUrl":null,"permalink":"/en/tags/randomized/","section":"Tags","summary":"","title":"Randomized","type":"tags"},{"content":" The original article is available at https://home.dawnmagnet.date/leetcode/2022/01/15/.\nHercy wants to save money to buy his first car. He deposits money into the Leetcode Bank every day.\nHe deposits 1 dollar on the first Monday. From Tuesday through Sunday, he deposits 1 dollar more each day than on the previous day. On every following Monday, he deposits 1 dollar more than he deposited on the previous Monday.\nGiven n, return the total amount of money he has deposited at the end of day n.\nExample 1:\n**Input:** n = 4 **Output:** 10 **Explanation:** After day 4, the total is 1 + 2 + 3 + 4 = 10. Example 2:\n**Input:** n = 10 **Output:** 37 **Explanation:** After day 10, the total is (1 + 2 + 3 + 4 + 5 + 6 + 7) + (2 + 3 + 4) = 37. Notice that Hercy deposits 2 dollars on the second Monday. Example 3:\n**Input:** n = 20 **Output:** 96 **Explanation:** After day 20, the total is (1 + 2 + 3 + 4 + 5 + 6 + 7) + (2 + 3 + 4 + 5 + 6 + 7 + 8) + (3 + 4 + 5 + 6 + 7 + 8) = 96. Constraints:\n1 \u0026lt;= n \u0026lt;= 1000 Source: LeetCode Link: https://leetcode-cn.com/problems/calculate-money-in-leetcode-bank Copyright belongs to LeetCode. For commercial use, contact the official copyright holder; for non-commercial use, cite the source as required.\nAnalysis # This is primarily a math problem. We need to compute the sum of a number sequence determined by the input n, so let us examine the pattern of that sequence.\nConsider the example from the problem:\n\\((1 + 2 + 3 + 4 + 5 + 6 + 7) + (2 + 3 + 4 + 5 + 6 + 7 + 8) + (3 + 4 + 5 + 6 + 7 + 8) = 96\\)\nTwo parts are easy to identify:\nThe first part consists of complete groups of seven, such as \\((1 + 2 + 3 + 4 + 5 + 6 + 7) + (2 + 3 + 4 + 5 + 6 + 7 + 8)\\). Each group contains exactly seven days. The other part, such as \\((3 + 4 + 5 + 6 + 7 + 8)\\), is an incomplete group of seven and can only occur at the end of the sequence. According to the problem statement, a complete group of seven represents one week; an incomplete group can only be the final group. We can split the computation into these two parts:\nFor the first part, sum the complete groups. The sums follow a clear pattern: \\(28,28+7,28+14,28+21,...\\) The second part is also an arithmetic progression, but its first term must be calculated from n. Assume \\(n=k*7+b\\), meaning k complete weeks plus b remaining days. The second progression can then be written as \\(k+1,k+2,k+3,...,k+b\\). Both sequences are arithmetic progressions, so we can use the arithmetic-series formula to compute them directly without a loop.\nPS: If you do not know the arithmetic-series formula, you can review it in elementary mathematics.\nThe first progression has first term \\(28\\), last term \\(21+7*k\\), and \\(k\\) terms. The second progression has first term \\(k+1\\), last term \\(k+b\\), and \\(b\\) terms.\nSubstituting these into the formula gives the final expression \\((49 + k * 7) * k / 2 + (2 * k + b + 1) * b / 2\\). There is no need to simplify it further, such as distributing k, because that may make the computer perform more operations.\nRust Code # impl Solution { pub fn total_money(n: i32) -\u0026gt; i32 { let k = n / 7; let b = n % 7; (49 + k * 7) * k / 2 + (2 * k + b + 1) * b / 2 } } ","date":"Jan 15, 2022","externalUrl":null,"permalink":"/en/leetcode/2022/01/15/","section":"LeetCode Solutions","summary":"","title":"LeetCode 1716: Calculate Money in Leetcode Bank","type":"leetcode"},{"content":"","date":"Jan 15, 2022","externalUrl":null,"permalink":"/en/tags/math/","section":"Tags","summary":"","title":"Math","type":"tags"},{"content":"","date":"Jan 14, 2022","externalUrl":null,"permalink":"/en/tags/heap/","section":"Tags","summary":"","title":"Heap","type":"tags"},{"content":" The original article is available at https://home.dawnmagnet.date/leetcode/2022/01/14/.\nGiven two integer arrays nums1 and nums2 sorted in ascending order, and an integer k, define a pair (u,v) whose first element comes from nums1 and whose second element comes from nums2.\nReturn the k pairs (u1,v1), (u2,v2) ... (uk,vk) with the smallest sums.\nExample 1:\n**Input:** nums1 = [1,7,11], nums2 = [2,4,6], k = 3 **Output:** [1,2],[1,4],[1,6] **Explanation:** The first 3 pairs in the sequence are: [1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6] Example 2:\n**Input:** nums1 = [1,1,2], nums2 = [1,2,3], k = 2 **Output:** [1,1],[1,1] **Explanation:** The first 2 pairs in the sequence are: [1,1],[1,1],[1,2],[2,1],[1,2],[2,2],[1,3],[1,3],[2,3] Example 3:\n**Input:** nums1 = [1,2], nums2 = [3], k = 3 **Output:** [1,3],[2,3] **Explanation:** All pairs in the sequence may be returned: [1,3],[2,3] Constraints:\n1 \u0026lt;= nums1.length, nums2.length \u0026lt;= 10E5 -10E9 \u0026lt;= nums1[i], nums2[i] \u0026lt;= 10E9 nums1 and nums2 are both sorted in ascending order. 1 \u0026lt;= k \u0026lt;= 1000 Source: LeetCode Link: https://leetcode-cn.com/problems/find-k-pairs-with-smallest-sums Copyright belongs to LeetCode. For commercial use, contact the official copyright holder; for non-commercial use, cite the source as required.\nAnalysis # The main idea is to find the smallest k elements. Problems asking for the smallest or largest k elements commonly use a heap. A heap may also be called a min-heap, max-heap, or priority queue; fundamentally, it maintains the heap property. In a max-heap, every parent is greater than its children, while in a min-heap every parent is smaller than its children. While maintaining this property, insertion and removal take only \\(O(lg(n))\\) time, allowing us to obtain several extreme values efficiently.\nHere, there are \\(m*n\\) possible values in total, because every pairwise sum of an element from the two arrays could be part of the result.\nWe maintain a max-heap called heap, whose size never exceeds k, the number of pairs required in the final answer. We first use two nested loops to add every possible pair to heap. Whenever the heap grows beyond k, remove its maximum. This still guarantees that the smallest k elements can be retained.\nThere are two useful optimizations (without them, the solution may time out):\nFrom the constraints, nums1 and nums2 may each contain up to \\(10^5\\) elements, while the answer contains at most 1000 pairs. There is no need to inspect every combination, so limit both loop variables to at most k. Every pair in the answer must come from pairing one of the first k elements of nums1 with one of the first k elements of nums2. During the traversal, we visit values from left to right. If the current value is greater than or equal to the maximum element in the heap, some combinations in the current inner loop no longer need to be examined, so we can break and skip them. Rust Code # use std::collections::BinaryHeap; impl Solution { pub fn k_smallest_pairs(nums1: Vec\u0026lt;i32\u0026gt;, nums2: Vec\u0026lt;i32\u0026gt;, k: i32) -\u0026gt; Vec\u0026lt;Vec\u0026lt;i32\u0026gt;\u0026gt; { let mut res = vec![]; let mut heap = BinaryHeap::new(); for i in 0..(nums1.len()).min(k as usize) { for j in 0..(nums2.len()).min(k as usize) { heap.push((nums1[i] + nums2[j], nums1[i], nums2[j])); if heap.len() \u0026gt; k as usize { if let Some((a, b, c)) = heap.pop() { if b == nums1[i] \u0026amp;\u0026amp; c == nums2[j] { break; } } } } } while heap.len() \u0026gt; 0 { if let Some((a, b, c)) = heap.pop() { res.push(vec![b, c]); } } res } } ","date":"Jan 14, 2022","externalUrl":null,"permalink":"/en/leetcode/2022/01/14/","section":"LeetCode Solutions","summary":"","title":"LeetCode 373: Find K Pairs with Smallest Sums","type":"leetcode"},{"content":"","date":"Jan 13, 2022","externalUrl":null,"permalink":"/en/tags/array/","section":"Tags","summary":"","title":"Array","type":"tags"},{"content":"Given an integer array nums, which always contains a unique largest integer, find the largest element and check whether it is at least twice every other number in the array. If so, return the index of the largest element; otherwise, return -1.\nExample 1:\n**Input:** nums = [3,6,1,0] **Output:** 1 **Explanation:** 6 is the largest integer, and it is greater than twice every other integer in the array. Its index is 1, so return 1. Example 2:\n**Input:** nums = [1,2,3,4] **Output:** -1 **Explanation:** 4 is not at least twice as large as 3, so return -1. Example 3:\n**Input:** nums = [1] **Output:** 0 **Explanation:** Because there are no other numbers, 1 is considered at least twice every other number. Constraints:\n1 \u0026lt;= nums.length \u0026lt;= 50 0 \u0026lt;= nums[i] \u0026lt;= 100 The largest element in nums is unique. Source: LeetCode Link: https://leetcode-cn.com/problems/largest-number-at-least-twice-of-others Copyright belongs to LeetCode. For commercial use, contact the official copyright holder; for non-commercial use, cite the source as required.\nAnalysis # The idea is straightforward. First find the largest integer, then determine whether it is at least twice every other number. Once the largest number is known, it is enough to compare it with the second-largest number: if twice the second-largest number is no greater than the largest number, all remaining numbers satisfy the condition as well.\nWe can find the largest and second-largest values in one pass. Use two variables, first and second, to store their indices (because the final answer is an index). During the traversal:\nCheck whether the current number is greater than the number at index first. If it is, the largest number becomes the current number. If it is greater than the number at index second and less than the number at index first, replace the second-largest value with the current number. If neither condition holds, do nothing. After one pass, we have the indices of both the largest and second-largest numbers. Compare the largest number with twice the second-largest number to obtain the answer.\nWe also need to handle special cases such as an array of length one and the initial values of the indices. Here, usize::MAX, the maximum value of usize, marks an uninitialized index. The corresponding conditions include checks such as first == usize::MAX; if first does not yet refer to a valid element, assign it first.\nRust Code # impl Solution { pub fn dominant_index(nums: Vec\u0026lt;i32\u0026gt;) -\u0026gt; i32 { let mut first = usize::MAX; let mut second = usize::MAX; for i in 0..nums.len() { if first == usize::MAX || nums[i] \u0026gt; nums[first] { second = first; first = i; } else if second == usize::MAX || nums[i] \u0026gt; nums[second] \u0026amp;\u0026amp; i != first { second = i; } } if second == usize::MAX || nums[first] \u0026gt;= nums[second] * 2 {first as i32} else {-1} } } ","date":"Jan 13, 2022","externalUrl":null,"permalink":"/en/leetcode/2022/01/13/","section":"LeetCode Solutions","summary":"","title":"LeetCode 747: Largest Number At Least Twice of Others","type":"leetcode"},{"content":" The original article is available at https://home.dawnmagnet.date/leetcode/2022/01/12/.\nGiven an integer array nums, determine whether the array contains an increasing subsequence of length 3.\nReturn true if there are indices (i, j, k) satisfying i \u0026amp;lt; j \u0026amp;lt; k and nums[i] \u0026amp;lt; nums[j] \u0026amp;lt; nums[k]; otherwise, return false.\nExample 1:\n**Input:**nums = [1,2,3,4,5] **Output:**true **Explanation:**Any triple of indices satisfying i \u0026lt; j \u0026lt; k meets the requirement Example 2:\n**Input:**nums = [5,4,3,2,1] **Output:**false **Explanation:**No triple of indices meets the requirement Example 3:\n**Input:**nums = [2,1,5,0,4,6] **Output:**true **Explanation:**The triple (3, 4, 5) meets the requirement because nums[3] == 0 \u0026lt; nums[4] == 4 \u0026lt; nums[5] == 6 Constraints:\n1 \u0026amp;lt;= nums.length \u0026amp;lt;= 5 * 10\u0026lt;sup\u0026gt;5\u0026lt;/sup\u0026gt; -2\u0026lt;sup\u0026gt;31\u0026lt;/sup\u0026gt; \u0026amp;lt;= nums[i] \u0026amp;lt;= 2\u0026lt;sup\u0026gt;31\u0026lt;/sup\u0026gt; - 1 Follow-up: Can you implement a solution with time complexity O(n) and space complexity O(1)?\nAnalysis # In this problem, we only need to find one triple that satisfies the conditions. A naive search over all triples would take \\(O(n^3)\\), which is clearly too slow. Let us first examine the conditions imposed on the triple.\nA triple has two requirements: increasing indices and increasing values. The index condition is straightforward. Since the target complexity is \\(O(n)\\), we make one pass from left to right. During that pass, we need to record the first one or two values of a potential triple so that we can complete it when a suitable value appears.\nAs we scan, we keep two variables, which we call first and second. They record the first two elements that could form a triple with the current element, since we scan from left to right. Because we only get one pass, we want to make it as easy as possible to complete the triple. A smaller value gives us more opportunities, so when a smaller number appears, we replace first or second as appropriate.\nThis replacement depends on the current number:\nWhen the current number is less than first, replace first with it. When the current number is less than second, replace second with it. When the current number is greater than second, we have found an increasing triplet, so return true. Therefore, one pass through the array is enough. If no answer is found, return false at the end.\nThis satisfies the follow-up requirement of \\(O(n)\\) time and \\(O(1)\\) space, because only a constant number of variables are used.\nRust Code # impl Solution { pub fn increasing_triplet(nums: Vec\u0026lt;i32\u0026gt;) -\u0026gt; bool { let mut first = nums[0]; let mut second = i32::MAX; for num in \u0026amp;nums[1..] { if num \u0026gt; \u0026amp;second { return true; } else if num \u0026gt; \u0026amp;first { second = *num; } else { first = *num; } } false } } ","date":"Jan 12, 2022","externalUrl":null,"permalink":"/en/leetcode/2022/01/12/","section":"LeetCode Solutions","summary":"","title":"LeetCode 334: Increasing Triplet Subsequence","type":"leetcode"},{"content":"There are n users on a social media website. You are given an integer array ages, where ages[i] is the age of the i-th user.\nIf any of the following conditions is true, user x will not send a friend request to user y (x != y):\nage[y] \u0026lt;= 0.5 * age[x] + 7 age[y] \u0026gt; age[x] age[y] \u0026gt; 100 \u0026amp;\u0026amp; age[x] \u0026lt; 100 Otherwise, x will send a friend request to y.\nNote that if x sends a friend request to y, y does not have to send one to x. Also, a user will not send a friend request to themselves.\nReturn the total number of friend requests sent on the social media website.\n\u0026nbsp;\nExample 1:\nInput:ages = [16,16] Output:2 Explanation:The two people send friend requests to each other. Example 2:\nInput:ages = [16,17,18] Output:2 Explanation:The friend requests are 17 -\u0026gt; 16 and 18 -\u0026gt; 17. Example 3:\nInput:ages = [20,30,100,110,120] Output:3 Explanation:The friend requests are 110 -\u0026gt; 100, 120 -\u0026gt; 110, and 120 -\u0026gt; 100. \u0026nbsp;\nConstraints:\nn == ages.length 1 \u0026lt;= n \u0026lt;= 2 * 104 1 \u0026lt;= ages[i] \u0026lt;= 120 Analysis # At first glance this problem seems easy, but it is more subtle than it looks. Problems defined by conditions often invite a brute-force pairwise comparison with O(n^2) complexity, but that approach is clearly not suitable here.\nInstead, look for conditions that can be exploited. There are three of them, and it is important to read their logic carefully: if any one condition is true, the request is not sent. Therefore, a request is sent only when all three conditions are false. The first condition means that y must be greater than 0.5x + 7; the second means that y must be less than or equal to x; and the third means that y \u0026gt; 100 and x \u0026lt; 100 must not both be true.\nTherefore, the input order does not matter. Count how many users have each age in an array, then perform the remaining calculations.\nNext use a two-pointer approach. After organizing the data, the ages are ordered, and for a specific sender age, the possible recipient ages lie within a certain interval. These intervals can overlap, so use prefix sums to perform the calculation.\nimpl Solution { pub fn num_friend_requests(ages: Vec\u0026lt;i32\u0026gt;) -\u0026gt; i32 { let (mut cnt, mut cs, mut res) = ([0; 121], [0; 121], 0); for age in ages { cnt[age as usize] += 1; } for i in 1..=120 { cs[i] = cs[i - 1] + cnt[i]; } for i in 15..=120 { res += cnt[i] * (cs[i] - cs[i / 2 + 7] - 1); } res } } The fourth line counts users by age, the fifth line computes the prefix sums, and the sixth line computes the final result. For a sender whose age is in the range 15–120, if the age is i, that sender can send friend requests to users whose ages lie in the range (i~i/2+7).\n","date":"Dec 27, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/12/27/","section":"LeetCode Solutions","summary":"","title":"LeetCode 825: Friends of Appropriate Ages","type":"leetcode"},{"content":"","date":"Dec 27, 2021","externalUrl":null,"permalink":"/en/tags/two-pointers/","section":"Tags","summary":"","title":"Two Pointers","type":"tags"},{"content":"Given the first word\u0026nbsp;first and the second word\u0026nbsp;second, consider every occurrence in a text\u0026nbsp;text of the form \"first second third\", where\u0026nbsp;second appears immediately after\u0026nbsp;first, and third appears immediately after\u0026nbsp;second.\nFor every such occurrence, add the third word \"third\" to the answer and return the answer.\n\u0026nbsp;\nExample 1:\nInput: text = \"alice is a good girl she is a good student\", first = \"a\", second = \"good\" Output: [\"girl\",\"student\"] Example 2:\nInput: text = \"we will we will rock you\", first = \"we\", second = \"will\" Output: [\"we\",\"rock\"] \u0026nbsp;\nConstraints:\n1 \u0026lt;= text.length \u0026lt;= 1000 text\u0026nbsp;consists of lowercase English letters and spaces. All words in text are separated by a single space character. 1 \u0026lt;= first.length, second.length \u0026lt;= 10 first and\u0026nbsp;second\u0026nbsp;consist of lowercase English letters. Analysis # While traversing the array, simply check whether the current words satisfy the conditions given in the problem.\nRust Code # impl Solution { pub fn find_ocurrences(text: String, first: String, second: String) -\u0026gt; Vec\u0026lt;String\u0026gt; { let mut is_one = false; let mut is_two = false; let mut res = vec![]; let mut pre1 = \u0026#34;\u0026#34;; let mut pre2 = \u0026#34;\u0026#34;; for word in text.split(\u0026#34; \u0026#34;) { if pre1 == first \u0026amp;\u0026amp; pre2 == second { res.push(word.to_string()); } pre1 = pre2; pre2 = word; } res } } ","date":"Dec 26, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/12/26/","section":"LeetCode Solutions","summary":"","title":"LeetCode 1078: Occurrences After Bigram","type":"leetcode"},{"content":"","date":"Dec 26, 2021","externalUrl":null,"permalink":"/en/tags/string/","section":"Tags","summary":"","title":"String","type":"tags"},{"content":"There is a special apple tree that grows for n consecutive days, producing some apples each day. On day i, the tree produces apples[i] apples. These apples will rot after days[i] days (that is, on day i + days[i]) and become inedible. There may also be days when no new apples grow, represented by apples[i] == 0 and days[i] == 0.\nYou plan to eat at most one apple each day to maintain a balanced diet. Note that you may continue eating apples after these n days.\nGiven two integer arrays days and apples, both of length n, return the maximum number of apples you can eat.\n\u0026nbsp;\nExample 1:\nInput: apples = [1,2,3,5,2], days = [3,2,1,4,2] Output: 7 Explanation: You can eat 7 apples: - On the first day, eat an apple that grew on the first day. - On the second day, eat an apple that grew on the second day. - On the third day, eat another apple that grew on the second day. After this day, the apples grown on the third day have already rotted. - From the fourth day through the seventh day, eat apples that grew on the fourth day. Example 2:\nInput: apples = [3,0,0,0,0,2], days = [3,0,0,0,0,2] Output: 5 Explanation: You can eat 5 apples: - From the first day through the third day, eat apples that grew on the first day. - Do not eat an apple on the fourth or fifth day. - On the sixth and seventh days, eat apples that grew on the sixth day. \u0026nbsp;\nConstraints:\napples.length == n days.length == n 1 \u0026lt;= n \u0026lt;= 2 * 104 0 \u0026lt;= apples[i], days[i] \u0026lt;= 2 * 104 days[i] = 0 only when apples[i] = 0 Analysis # Because you can eat at most one apple per day, the optimal strategy is to eat the apple that will expire earliest after the current day. This strategy is also common in everyday life: people generally eat the food they own that is closest to its expiration date first, which minimizes waste and lets them eat as many apples as possible.\nFollowing this strategy, use an array rots to record when apples expire, and use eatId to track the expiration day of the earliest apple currently available. On each day, we only need to do the following (assume the current day is i and array indices start at 1, as in the problem statement):\nFirst ensure that eatId, the earliest expiration day among the apples that can currently be eaten, is at least the current day. Then process the apples harvested today. If today produces a apples that rot after n days, add them to rots by setting rots[i + n - 1] += a. We cannot eat this batch on day i+n, so its last edible day is i+n-1. Finally choose an apple to eat. If eatId is later than the expiration day of today\u0026rsquo;s new batch, set eatId to today\u0026rsquo;s expiration day; in other words, if today\u0026rsquo;s new apples rot sooner, eat them first. After choosing an edible apple (if rots[eatId] is zero, there are no apples left on the currently selected day, so advance eatId to a day that still has apples; by definition, eatId is the nearest expiration day, so it can only move forward), increment the answer and decrement rots[eatId] by 1. If no apples remain, eat nothing. Rust Code # impl Solution { pub fn eaten_apples(apples: Vec\u0026lt;i32\u0026gt;, days: Vec\u0026lt;i32\u0026gt;) -\u0026gt; i32 { let mut rots = [0; 40005]; let mut eatId = 0; let mut res = 0; for index in 1..40003 { eatId = eatId.max(index); if index \u0026lt;= apples.len() \u0026amp;\u0026amp; apples[index - 1] != 0 { rots[index - 1 + days[index - 1] as usize] += apples[index - 1]; eatId = eatId.min(index - 1 + days[index - 1] as usize); } while rots[eatId] == 0 \u0026amp;\u0026amp; eatId \u0026lt; 40002 { eatId += 1; } if eatId != 40002 { rots[eatId] -= 1; res += 1; } } res } } ","date":"Dec 24, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/12/24/","section":"LeetCode Solutions","summary":"","title":"LeetCode 1705: Maximum Number of Eaten Apples","type":"leetcode"},{"content":" Given two strings\u0026nbsp;a and b, find the minimum number of repetitions of string a such that b is a substring of the repeated string. Return -1 if this is impossible. Note: Repeating the string \"abc\"\u0026nbsp;0 times produces \"\", repeating it 1 time produces\u0026nbsp;\"abc\", and repeating it 2 times produces\u0026nbsp;\"abcabc\". \u0026nbsp;\nExample 1:\nInput:a = \"abcd\", b = \"cdabcdab\" Output:3 Explanation:After repeating a three times, the result is \"abcdabcdabcd\", so b is a substring. Example 2:\nInput:a = \"a\", b = \"aa\" Output:2 Example 3:\nInput:a = \"a\", b = \"a\" Output:1 Example 4:\nInput:a = \"abc\", b = \"wxyz\" Output:-1 \u0026nbsp;\nConstraints:\n1 \u0026lt;= a.length \u0026lt;= 104 1 \u0026lt;= b.length \u0026lt;= 104 a and b consist of lowercase English letters. Analysis # First obtain the lengths of the two strings, a and b. Let n be the ceiling of b/a. According to the problem, b can only be a substring of a repeated n times, a repeated n+1 times, or neither. If neither contains b, return -1.\nRust Code # impl Solution { pub fn repeated_string_match(a: String, b: String) -\u0026gt; i32 { let (lb, la) = (b.len(), a.len()); let times = ((lb as f64) / (la as f64)).ceil() as usize; if a.repeat(times).contains(\u0026amp;b) { times as i32 } else if a.repeat(times + 1).contains(\u0026amp;b) { times as i32 + 1 } else { -1 } } } ","date":"Dec 22, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/12/22/","section":"LeetCode Solutions","summary":"","title":"LeetCode 686: Repeated String Match","type":"leetcode"},{"content":"","date":"Dec 21, 2021","externalUrl":null,"permalink":"/en/tags/date-and-time/","section":"Tags","summary":"","title":"Date and Time","type":"tags"},{"content":" Given a string\u0026nbsp;date representing a date in the YYYY-MM-DD format under the Common Era, calculate and return the ordinal day of that date within its year. Normally, January 1 is the first day of every year, January 2 is the second day, and so on. The number of days in each month follows the Gregorian calendar. \u0026nbsp;\nExample 1:\nInput:date = \"2019-01-09\" Output:9 Example 2:\nInput:date = \"2019-02-10\" Output:41 Example 3:\nInput:date = \"2003-03-01\" Output:60 Example 4:\nInput:date = \"2004-03-01\" Output:61 \u0026nbsp;\nConstraints:\ndate.length == 10 date[4] == date[7] == '-'; all other\u0026nbsp;date[i]\u0026nbsp;are digits date ranges from January 1, 1900, to December 31, 2019 Analysis # Split the date, determine whether the year is a leap year, and then sum the days.\nCode (Rust) # impl Solution { pub fn day_of_year(date: String) -\u0026gt; i32 { let v: Vec\u0026lt;i32\u0026gt; = date.split(\u0026#39;-\u0026#39;).map(|x| x.parse().unwrap()).collect(); let mut days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; if v[1] \u0026gt; 2 \u0026amp;\u0026amp; v[0] % 4 == 0 \u0026amp;\u0026amp; (v[0] % 100 != 0 || v[0] % 400 == 0) { days[1] += 1; } \u0026amp;days[0..(v[1] as usize - 1)].iter().sum() + v[2] } } Code (Go) # func dayOfYear(date string) int { t, _ := time.Parse(\u0026#34;2006-01-02\u0026#34;, date) return t.YearDay() } ","date":"Dec 21, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/12/21/","section":"LeetCode Solutions","summary":"","title":"LeetCode 1154: Day of the Year","type":"leetcode"},{"content":"","date":"Dec 20, 2021","externalUrl":null,"permalink":"/en/tags/binary-search/","section":"Tags","summary":"","title":"Binary Search","type":"tags"},{"content":" Winter has arrived.\u0026nbsp;Your task is to design heaters with a fixed heating radius to warm all the houses. Every house within the heating radius of a heater can receive heat.\nGiven the positions of the houses\u0026nbsp;houses and heaters\u0026nbsp;heaters on a horizontal line, find and return the minimum heating radius that covers every house. Note: All heaters use the same radius specified by you, so their heating radii are identical. \u0026nbsp;\nExample 1:\nInput: houses = [1,2,3], heaters = [2] Output: 1 Explanation: There is one heater at position 2. If we set the heating radius to 1, every house can be heated. Example 2:\nInput: houses = [1,2,3,4], heaters = [1,4] Output: 1 Explanation: There are two heaters at positions 1 and 4. We need a heating radius of 1 to heat every house. Example 3:\nInput:houses = [1,5], heaters = [2] Output:3 \u0026nbsp;\nConstraints:\n1 \u0026lt;= houses.length, heaters.length \u0026lt;= 3 * 104 1 \u0026lt;= houses[i], heaters[i] \u0026lt;= 109","date":"Dec 20, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/12/20/","section":"LeetCode Solutions","summary":"","title":"LeetCode 475: Heaters","type":"leetcode"},{"content":"Count the number of words in a string, where a word is a contiguous sequence of non-space characters.\nNote that you may assume the string does not contain any non-printable characters.\nExample:\nInput: \"Hello, my name is John\" Output: 5 Explanation: A word is a contiguous sequence of non-space characters, so \"Hello,\" counts as one word. Analysis # This problem is somewhat like a state machine. We need to maintain whether the previous character was part of a word. If the previous character is a space and the next one is not, a new word has started.\nRust Code # # struct Solution; impl Solution { pub fn count_segments(s: String) -\u0026gt; i32 { let mut state = 0; let mut res = 0; for ch in s.chars() { if ch == \u0026#39; \u0026#39; { state = 0; } else { if state == 0 { res += 1; } state = 1; } } res } } ","date":"Oct 7, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/10/07/","section":"LeetCode Solutions","summary":"","title":"LeetCode 434: Number of Segments in a String","type":"leetcode"},{"content":"Given a non-empty array, return the third-largest number in the array. If it does not exist, return the largest number in the array.\n\u0026nbsp;\nExample 1:\nInput:[3, 2, 1] Output:1 Explanation:The third-largest number is 1. Example 2:\nInput:[1, 2] Output:2 Explanation:The third-largest number does not exist, so return the largest number, 2. Example 3:\nInput:[2, 2, 3, 1] Output:1 Explanation:Remember that the third-largest number means the third-largest number among all distinct values. There are two values equal to 2, and both rank second. The third-largest distinct value is 1. \u0026nbsp;\nConstraints:\n1 \u0026lt;= nums.length \u0026lt;= 104 -231 \u0026lt;= nums[i] \u0026lt;= 231 - 1 \u0026nbsp;\nFollow-up: Can you design a solution with O(n) time complexity?\nAnalysis # For this type of problem, a sorted array is usually enough.\nFor an O(n) solution, maintain a sorted array whose size never exceeds three, because any additional elements are not needed.\nRust Code # # struct Solution; use std::collections::BTreeSet; impl Solution { pub fn third_max(mut nums: Vec\u0026lt;i32\u0026gt;) -\u0026gt; i32 { let mut set = BTreeSet::new(); for item in nums { set.insert(item); } *set.iter().rev().nth(2).unwrap_or(set.iter().last().unwrap()) } } ","date":"Oct 6, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/10/06/","section":"LeetCode Solutions","summary":"","title":"LeetCode 414: Third Maximum Number","type":"leetcode"},{"content":"","date":"Oct 5, 2021","externalUrl":null,"permalink":"/en/tags/iterator/","section":"Tags","summary":"","title":"Iterator","type":"tags"},{"content":"Design an iterator that supports a peek operation in addition to hasNext and next.\nImplement the PeekingIterator class:\nPeekingIterator(int[] nums) initializes the iterator with the specified integer array nums. int next() returns the next element in the array and moves the pointer to the following element. bool hasNext() returns true if another element exists in the array; otherwise, it returns false. int peek() returns the next element in the array but does not move the pointer. \u0026nbsp;\nExample:\nInput: [\"PeekingIterator\", \"next\", \"peek\", \"next\", \"next\", \"hasNext\"] [[[1, 2, 3]], [], [], [], [], []] Output: [null, 1, 2, 2, 3, false] Explanation: PeekingIterator peekingIterator = new PeekingIterator([1, 2, 3]); // [1,2,3] peekingIterator.next(); // returns 1 and moves the pointer to the next element [1,2,3] peekingIterator.peek(); // returns 2 without moving the pointer [1,2,3] peekingIterator.next(); // returns 2 and moves the pointer to the next element [1,2,3] peekingIterator.next(); // returns 3 and moves the pointer to the next element [1,2,3] peekingIterator.hasNext(); // returns False \u0026nbsp;\nConstraints:\n1 \u0026lt;= nums.length \u0026lt;= 1000 1 \u0026lt;= nums[i] \u0026lt;= 1000 All calls to next and peek are valid. next, hasNext, and peek are called at most 1000 times. \u0026nbsp;\nFollow-up: How would you extend your design to make it generic so that it works with all types, rather than only integers?\nAnalysis # The main difficulty is that the Iterator data structure provided by the original problem exposes only these two interfaces:\nint next() bool hasNext() Our data structure must add a third interface, int peek(), on top of them.\nThis creates a problem: every call to next() unquestionably moves the iterator forward by one position, while a call to peek() does not.\nOne straightforward idea is to save a number every time next() is called and use it as the return value for the next call to peek(). However, that approach has a problem.\nAs Example 1 shows, calling peek() does not move the pointer, but it still retrieves the value of the next element. The challenge is to obtain the next element\u0026rsquo;s value without moving the pointer, even though next() always moves it.\nThe approach is to keep the next element\u0026rsquo;s value in a variable. If peek() is called, return this stored value. If next() is called, return the stored value as well, then update the stored value to the following element.\nC++ Code # class PeekingIterator : public Iterator { public: PeekingIterator(const vector\u0026lt;int\u0026gt;\u0026amp; nums) : Iterator(nums) { flag = Iterator::hasNext(); if (flag) { nextElement = Iterator::next(); } } int peek() { return nextElement; } int next() { int ret = nextElement; flag = Iterator::hasNext(); if (flag) { nextElement = Iterator::next(); } return ret; } bool hasNext() const { return flag; } private: int nextElement; bool flag; }; ","date":"Oct 5, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/10/05/","section":"LeetCode Solutions","summary":"","title":"LeetCode 284: Peeking Iterator","type":"leetcode"},{"content":"There is a key string S containing only letters, digits, and '-' (dashes). The N dashes divide the string into N+1 groups.\nGiven a number K, reformat the string so that each group contains exactly K characters. In particular, the first group must contain at most K characters, but at least 1 character. Separate adjacent groups with '-' (dashes), and convert all lowercase letters to uppercase.\nGiven a non-empty string S and a number K, format the string according to the rules above.\n\u0026nbsp;\nExample 1:\nInput:S = \"5F3Z-2e-9-w\", K = 4 Output:\"5F3Z-2E9W\" Explanation:The string S is split into two groups, each containing 4 characters; \u0026nbsp; note that the two extra dashes must be removed. Example 2:\nInput:S = \"2-5g-3-J\", K = 2 Output:\"2-5G-3J\" Explanation:The string S is split into 3 groups. According to the rules above, the first group may contain fewer than the specified number of characters, while every other group contains 2 characters. \u0026nbsp;\nConstraints:\nS may be very long, so allocate memory as needed. K is a positive integer. S contains only letters, digits (a-z, A-Z, 0-9), and the dash '-'. S is non-empty. \u0026nbsp;\nAnalysis # According to the problem, the dashes in the original string are not useful, so remove them while counting.\nFirst calculate how many characters can be assigned to each group, represented by the variable parts. Then calculate how many characters belong in the first group, represented by remains. If the valid character count is divisible by K, the first group contains K characters; otherwise, it contains fewer than K characters, namely the number of valid characters divided by k.\nOnce these values have been calculated, fill the characters from the original string into the result. After filling remains characters, insert a dash and reset remains to K, because every subsequent group contains K characters.\nRust Code # # struct Solution; impl Solution { pub fn license_key_formatting(s: String, k: i32) -\u0026gt; String { let k = k as usize; let n = s.len(); let count = s.chars().fold(0, |acc, x| acc + (x == \u0026#39;-\u0026#39;) as usize); let valid = n - count; let parts = valid / k + (valid % k \u0026gt; 0) as usize; let mut remains = if valid % k == 0 {k} else {valid % k}; let mut res = \u0026#34;\u0026#34;.to_string(); for ch in s.chars() { if ch == \u0026#39;-\u0026#39; { continue; } if remains == 0 { res.push(\u0026#39;-\u0026#39;); remains = k; } res.push(ch.to_ascii_uppercase()); remains -= 1; } res } } ","date":"Oct 4, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/10/04/","section":"LeetCode Solutions","summary":"","title":"LeetCode 482: License Key Formatting","type":"leetcode"},{"content":"Given two integers representing the numerator numerator and denominator denominator of a fraction, return its decimal representation as a string.\nIf the fractional part is repeating, enclose the repeating portion in parentheses.\nIf there are multiple possible answers, return any one of them.\nFor every given input, the answer string is guaranteed to have a length less than 104.\n\u0026nbsp;\nExample 1:\nInput:numerator = 1, denominator = 2 Output:\"0.5\" Example 2:\nInput:numerator = 2, denominator = 1 Output:\"2\" Example 3:\nInput:numerator = 2, denominator = 3 Output:\"0.(6)\" Example 4:\nInput:numerator = 4, denominator = 333 Output:\"0.(012)\" Example 5:\nInput:numerator = 1, denominator = 5 Output:\"0.2\" \u0026nbsp;\nConstraints:\n-231 \u0026lt;=\u0026nbsp;numerator, denominator \u0026lt;= 231 - 1 denominator != 0 Analysis # The core of this problem is to solve it using the reasoning behind long division. How can we detect a repeating decimal while performing division?\nFirst, preprocess the input with the following steps:\nNormalize the sign. Dividing two positive numbers is clearly easier to reason about. Convert all 32-bit input values to 64-bit values because they may overflow. Process the integer part, which generally does not belong to the repeating fractional portion. Handle the other special cases. After these steps, we still have the two values from the problem, numerator and denominator. They are still the dividend and divisor, but after removing the integer part, we can guarantee that numerator is smaller than denominator. If you are stuck, take a look at the image above. It essentially summarizes the mathematical ideas about recurring decimals needed for this problem. During division, when a number does not divide evenly, we use the remainder and continue by multiplying the remainder by 10 before dividing again. Once a remainder repeats, everything that follows is identical as well; in other words, the first occurrence of the repeated remainder marks the beginning of the recurring cycle.\nHere we use a hash map to store every remainder seen so far. When a remainder appears for the second time, mark the position where the cycle begins and terminate the program.\nRust Code # # struct Solution; use std::collections::HashMap; impl Solution { pub fn fraction_to_decimal(numerator: i32, denominator: i32) -\u0026gt; String { let mut ret = String::new(); if (numerator as i64 * denominator as i64) \u0026lt; 0 { ret.push(\u0026#39;-\u0026#39;); } let mut denominator = (denominator as i64).abs(); let mut numerator = (numerator as i64).abs(); let pre = numerator / denominator; numerator %= denominator; let mut map: HashMap\u0026lt;i64, i32\u0026gt; = HashMap::new(); ret.push_str(\u0026amp;pre.to_string()); if numerator == 0 { return ret; } ret.push(\u0026#39;.\u0026#39;); let mut ws = ret.len() as i32; loop { if numerator == 0 { break; } if map.contains_key(\u0026amp;numerator) { ret.insert(*map.get(\u0026amp;numerator).unwrap() as usize, \u0026#39;(\u0026#39;); ret.push(\u0026#39;)\u0026#39;); break; } map.insert(numerator, ws); numerator *= 10; ret.push(((\u0026#39;0\u0026#39; as u8) + (numerator / denominator) as u8) as char); numerator %= denominator; ws += 1; } ret } } ","date":"Oct 3, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/10/03/","section":"LeetCode Solutions","summary":"","title":"LeetCode 166: Fraction to Recurring Decimal","type":"leetcode"},{"content":"","date":"Oct 2, 2021","externalUrl":null,"permalink":"/en/tags/bit-manipulation/","section":"Tags","summary":"","title":"Bit Manipulation","type":"tags"},{"content":"Given an integer, write an algorithm to convert it to a hexadecimal number. For negative integers, we normally use\u0026nbsp;two's-complement arithmetic.\nNote:\nAll letters (a-f) in the hexadecimal representation must be lowercase. The hexadecimal string must not contain unnecessary leading zeroes. If the number to convert is 0, represent it with the single character '0'; otherwise, the first character of the hexadecimal string must not be 0.\u0026nbsp; The given number is guaranteed to be within the range of a 32-bit signed integer. You may not use any library-provided method that directly converts or formats a number as hexadecimal. Example 1:\nInput: 26 Output: \"1a\" Example 2:\nInput: -1 Output: \"ffffffff\" Analysis # This is essentially a binary-to-hexadecimal conversion. It is best to use bitwise operations, which make efficient use of the computer\u0026rsquo;s binary architecture.\nOne hexadecimal digit corresponds to four binary digits.\nRust Code # impl Solution { pub fn to_hex(num: i32) -\u0026gt; String { let turned: Vec\u0026lt;char\u0026gt; = \u0026#34;0123456789abcdef\u0026#34;.chars().collect(); let mut num = num as u32; if num == 0 { return \u0026#34;0\u0026#34;.to_string(); } let mut res = vec![]; while num != 0 { let mut tmp = 0; for i in 0..4 { tmp += (num \u0026amp; 1) * (1 \u0026lt;\u0026lt; i); num \u0026gt;\u0026gt;= 1; } res.push(turned[tmp as usize]); } res.reverse(); res.iter().collect() } } C++ Code # static const char * turned = \u0026#34;0123456789abcdef\u0026#34;; class Solution { public: string toHex(unsigned int num) { string res; do { int tmp = 0; for (int i = 0; i \u0026lt; 4; ++i) { tmp += (num \u0026amp; 1) * (1 \u0026lt;\u0026lt; i); num \u0026gt;\u0026gt;= 1; } res.push_back(turned[tmp]); } while (num != 0); reverse(res.begin(), res.end()); return res; } }; ","date":"Oct 2, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/10/02/","section":"LeetCode Solutions","summary":"","title":"LeetCode 405: Convert a Number to Hexadecimal","type":"leetcode"},{"content":"Given a travel route map represented by the array paths, where paths[i] = [cityAi, cityBi] means that the route goes directly from cityAi to cityBi, find the destination city: the city with no route leading to another city.\nThe input guarantees that the route map forms a path with no cycles, so there is exactly one destination city.\n\u0026nbsp;\nExample 1:\nInput:paths = [[\"London\",\"New York\"],[\"New York\",\"Lima\"],[\"Lima\",\"Sao Paulo\"]] Output:\"Sao Paulo\" Explanation:Starting from \"London\", the trip finally reaches the destination city \"Sao Paulo\". The route is \"London\" -\u0026gt; \"New York\" -\u0026gt; \"Lima\" -\u0026gt; \"Sao Paulo\". Example 2:\nInput:paths = [[\"B\",\"C\"],[\"D\",\"B\"],[\"C\",\"A\"]] Output:\"A\" Explanation:The possible routes are: \"D\" -\u0026gt; \"B\" -\u0026gt; \"C\" -\u0026gt; \"A\".\u0026nbsp; \"B\" -\u0026gt; \"C\" -\u0026gt; \"A\".\u0026nbsp; \"C\" -\u0026gt; \"A\".\u0026nbsp; \"A\".\u0026nbsp; Clearly, the destination city is \"A\". Example 3:\nInput:paths = [[\"A\",\"Z\"]] Output:\"Z\" \u0026nbsp;\nConstraints:\n1 \u0026lt;= paths.length \u0026lt;= 100 paths[i].length == 2 1 \u0026lt;=\u0026nbsp;cityAi.length,\u0026nbsp;cityBi.length \u0026lt;= 10 cityAi\u0026nbsp;!=\u0026nbsp;cityBi All strings consist of uppercase and lowercase English letters and spaces. Analysis # The destination city has no next city to visit, so it never appears as the first element A in a pair (A, B); it appears only as a B. Therefore, store all A values in a hash set, then iterate over every B and check whether it is in the set. The first city that is not found is the answer.\nJava Code # class Solution { public String destCity(List\u0026lt;List\u0026lt;String\u0026gt;\u0026gt; paths) { int len = paths.size(); Set\u0026lt;String\u0026gt; set = new HashSet\u0026lt;\u0026gt;(); paths.forEach((path) -\u0026gt; { set.add(path.get(0)); }); for (int i = 0; i \u0026lt; len; i++) { List\u0026lt;String\u0026gt; list = paths.get(i); if (!set.contains(list.get(1))) { return list.get(1); } } return null; } } ","date":"Oct 1, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/10/01/","section":"LeetCode Solutions","summary":"","title":"LeetCode 1436: Destination City","type":"leetcode"},{"content":"Suppose there are n\u0026nbsp;super washing machines arranged in a row. Initially, each machine may contain some clothes or be empty.\nIn each step, you may choose any m (1 \u0026lt;= m \u0026lt;= n) washing machines. At the same time, each selected machine sends one piece of clothing to an adjacent machine.\nGiven an integer array\u0026nbsp;machines representing the number of clothes in each washing machine from left to right, return the minimum number of steps needed to make the number of clothes remaining in every machine equal. If it is impossible, return -1.\n\u0026nbsp;\nExample 1:\nInput:machines = [1,0,5] Output:3 Explanation: First step: 1 0 \u0026lt;-- 5 =\u0026gt; 1 1 4 Second step: 1 \u0026lt;-- 1 \u0026lt;-- 4 =\u0026gt; 2 1 3 Third step: 2 1 \u0026lt;-- 3 =\u0026gt; 2 2 2 Example 2:\nInput:machines = [0,3,0] Output:2 Explanation: First step: 0 \u0026lt;-- 3 0 =\u0026gt; 1 2 0 Second step: 1 2 --\u0026gt; 0 =\u0026gt; 1 1 1 Example 3:\nInput:machines = [0,2,0] Output:-1 Explanation: It is impossible to make all three washing machines contain the same number of clothes. \u0026nbsp;\nConstraints:\nn == machines.length 1 \u0026lt;= n \u0026lt;= 104 0 \u0026lt;= machines[i] \u0026lt;= 105 Approach # The main idea is to traverse the array.\nFirst, make one pass to determine whether a solution is possible and to calculate the average number of clothes, avg, for each position.\nThe next step follows from an important observation. If a position contains K pieces of clothing and K\u0026gt;avg, the final answer must be at least K-avg. Regardless of what happens at the other machines, this machine must spend K-avg steps sending away its excess clothes.\nWe can also maintain a value cur while traversing the array. Imagine an invisible hand changing the number of clothes in every machine to avg as it moves across the array. Excess clothes are treated as surplus, while missing clothes are treated as a deficit. This has the benefit of assigning each transfer to the relevant boundary. The following example makes this easier to understand.\n示例： [5, 0, 7], avg = 12 / 3 = 4 在遍历时的`cur`值：[1, -3, 0] For this array, the maximum absolute value of cur is the total time required. If we look only at position 1, the middle position, we see that it needs four fills to reach avg. One fill comes from the left and three come from the right, but these two periods can overlap. The value of cur represents deficits and surpluses well. When the deficit at a position is k, it means that even after balancing the machines to its left internally, they are still short of k items, which must be moved over from the right of cur; this k is the minimum transfer time. When the surplus is k, it similarly means that the machines at and to the left of cur have k extra items after internal balancing. They must be transferred to the right of cur, and the transfer must pass through cur, so these k moves cannot overlap and require at least k steps.\nThus, cur controls the global number of transfers. There is still one limitation. Consider the following example:\n示例： [0, 3, 0], avg = 3 / 3 = 1 在遍历时的`cur`值：[-1, 1, 0] In this example, cur misses a crucial point: the machine containing 3 pieces must spend two steps to transfer all its excess clothes. But cur does not know that the values -1 and 1 it encounters cannot overlap; both come from the machine containing 3. We therefore need to consider the effects of both cur and K-avg on the final result.\nRust Code # # struct Solution; impl Solution { pub fn find_min_moves(machines: Vec\u0026lt;i32\u0026gt;) -\u0026gt; i32 { let sum: i32 = machines.iter().sum(); let n = machines.len() as i32; if sum % n != 0 { return -1; } let avg = sum / n; let mut res = 0; let mut cur = 0; for mut m in machines { m -= avg; cur += m; res = res.max(cur.abs()).max(m); } res } } C++ Code # class Solution { public: int findMinMoves(vector\u0026lt;int\u0026gt;\u0026amp; m) { int n = m.size(); int sum = 0; for (auto \u0026amp; t : m) sum += t; if (sum % n != 0) return -1; int per = sum / n; sum = 0; int res = 0; for (auto \u0026amp; t : m) { t -= per; sum += t; res = max(res, abs(sum)); res = max(res, t); } return res; } }; ","date":"Sep 29, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/09/29/","section":"LeetCode Solutions","summary":"","title":"LeetCode 517: Super Washing Machines","type":"leetcode"},{"content":"A message containing the letters\u0026nbsp;A-Z is encoded as follows:\n'A' -\u0026gt; 1 'B' -\u0026gt; 2 ... 'Z' -\u0026gt; 26 To decode an encoded message, all digits must be grouped and then mapped back to letters according to the original encoding scheme. There may be multiple ways to do this. For example, \"11106\" can be mapped as follows:\n\"AAJF\" corresponds to the grouping (1 1 10 6) \"KJF\" corresponds to the grouping (11 10 6) Note that a grouping such as (1 11 06) is invalid because \"06\" cannot be mapped to 'F': \"6\" and \"06\" are different.\nIn addition to the digit-to-letter mapping described above, the encoded message may contain the character '*', which can represent any digit from '1' to '9' (but not '0'). For example, the encoded string \"1*\" can represent any of \"11\", \"12\", \"13\", \"14\", \"15\", \"16\", \"17\", \"18\", or \"19\". Decoding \"1*\" means counting the decodings of every encoded message it can represent.\nGiven a string s consisting of digits and the character '*', return the number of ways to decode it.\nBecause the number of ways may be very large, return the result modulo 109 + 7.\n\u0026nbsp;\nExample 1:\nInput:s = \"*\" Output:9 Explanation:This encoded message can represent any of \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", or \"9\". They can be decoded into \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\", and \"I\", respectively. Therefore, \"*\" has 9 possible decodings. Example 2:\nInput:s = \"1*\" Output:18 Explanation:This encoded message can represent any of \"11\", \"12\", \"13\", \"14\", \"15\", \"16\", \"17\", \"18\", or \"19\". Each message can be decoded in 2 ways (for example, \"11\" can be decoded as \"AA\" or \"K\"). Therefore, \"1*\" has 9 * 2 = 18 possible decodings. Example 3:\nInput:s = \"2*\" Output:15 Explanation:This encoded message can represent any of \"21\", \"22\", \"23\", \"24\", \"25\", \"26\", \"27\", \"28\", or \"29\". \"21\", \"22\", \"23\", \"24\", \"25\", and \"26\" each have 2 decodings, while \"27\", \"28\", and \"29\" each have only 1 decoding. Therefore, \"2*\" has (6 * 2) + (3 * 1) = 12 + 3 = 15 possible decodings. \u0026nbsp;\nConstraints:\n1 \u0026lt;= s.length \u0026lt;= 105 s[i] is a digit from 0 - 9 or the character '*' Approach # This problem mainly tests the rigor of the reasoning.\nThe information in the statement makes it clear that this is a one-dimensional dynamic-programming problem. The idea is also a standard dynamic-programming recurrence: dp[i] is the number of ways to decode all strings formed by the first i characters of s.\nIf s[i] is not \u0026lsquo;0\u0026rsquo;, it can form a decoding on its own, so dp[i + 1] += dp[i]. If s[i - 1] and s[i] can form a number greater than or equal to 10 (this is a major pitfall because \u0026ldquo;01\u0026rdquo; is invalid) and less than or equal to 26, we can treat the two digits as one decoding, so dp[i + 1] += dp[i - 1]. The idea is simple, but the implementation is complicated because it is easy to overlook various cases, such as the fact that \u0026quot;*\u0026quot; can represent only 1 through 9 and \u0026ldquo;01\u0026rdquo; is not a valid number.\nThe main strategy is to split the cases. For s[i] and s[i-1], there are four cases depending on whether each is \u0026quot;*\u0026quot;. Handling them separately avoids omissions.\nC++ Code # using ll = int64_t; class Solution { public: int numDecodings(string s) { int n = s.size(); ll dp[n + 1]; memset(dp, 0, sizeof dp); dp[0] = 1; for (int i = 0; i \u0026lt; n; ++i) { if (s[i] == \u0026#39;*\u0026#39;) dp[i + 1] += dp[i] * 9; else if (s[i] != \u0026#39;0\u0026#39;) dp[i + 1] += dp[i]; if (i \u0026gt; 0) { // cout \u0026lt;\u0026lt; \u0026#34;Good\u0026#34;; if (s[i - 1] == \u0026#39;*\u0026#39; \u0026amp;\u0026amp; s[i] != \u0026#39;*\u0026#39;){ if (s[i] \u0026lt;= \u0026#39;6\u0026#39;) dp[i + 1] += 2 * dp[i - 1]; else dp[i + 1] += dp[i - 1]; } else if (s[i - 1] == \u0026#39;*\u0026#39; \u0026amp;\u0026amp; s[i] == \u0026#39;*\u0026#39;) { // cout \u0026lt;\u0026lt; \u0026#34;Good\u0026#34;; dp[i + 1] += dp[i - 1] * 15; } else if (s[i - 1] != \u0026#39;*\u0026#39; \u0026amp;\u0026amp; s[i] == \u0026#39;*\u0026#39;) { if (s[i - 1] == \u0026#39;1\u0026#39;) dp[i + 1] += dp[i - 1] * 9; else if (s[i - 1] == \u0026#39;2\u0026#39;) dp[i + 1] += dp[i - 1] * 6; } else { if (s[i - 1] == \u0026#39;1\u0026#39; || (s[i - 1] == \u0026#39;2\u0026#39; \u0026amp;\u0026amp; s[i] \u0026lt;= \u0026#39;6\u0026#39;)) dp[i + 1] += dp[i - 1]; } } dp[i + 1] %= ll(1e9 + 7); } return dp[n]; } }; ","date":"Sep 27, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/09/27/","section":"LeetCode Solutions","summary":"","title":"LeetCode 639: Decode Ways II","type":"leetcode"},{"content":"Given two integers a and b, calculate and return their sum without using the operators\u0026nbsp;+ and\u0026nbsp;-.\n\u0026nbsp;\nExample 1:\nInput:a = 1, b = 2 Output:3 Example 2:\nInput:a = 2, b = 3 Output:5 \u0026nbsp;\nConstraints:\n-1000 \u0026lt;= a, b \u0026lt;= 1000 Approach # First, let us explain what an adder is.\nAn adder, as its name suggests, is a tool for performing addition. A two-input binary adder should have two outputs: one is the sum bit, and the other is the carry.\nHere is the corresponding table:\nNumber 1 Number 2 Result Sum bit Carry 0 0 0 0 0 1 0 1 1 0 0 1 1 1 0 1 1 10 0 1 From the table above, we can see that the final result consists of the sum bit and the carry.\nFor binary numbers, the sum-bit operation is clearly an XOR operation, while the carry operation is an AND operation. Therefore, we obtain the equation:\na + b = a ^ b + (a \u0026amp; b) * 2 That is, a + b = a ^ b + (a \u0026amp; b) \u0026laquo; 1 We have changed one plus sign into another plus sign, which does not seem very useful.\nIn this situation, however, we can consider whether recursion is possible. Notice that a \u0026amp; b is guaranteed to become smaller and smaller, eventually approaching 0. Once b approaches 0, the answer is a, which gives us the base case for recursion.\nRust Code # # struct Solution; impl Solution { pub fn get_sum(a: i32, b: i32) -\u0026gt; i32 { if b == 0 { a } else { Solution::get_sum(a ^ b, (a \u0026amp; b) \u0026lt;\u0026lt; 1) } } } C++ Code # class Solution { public: unsigned getSum(unsigned a, unsigned b) { if (b == 0) return a; return getSum(a ^ b, (a \u0026amp; b) \u0026lt;\u0026lt; 1); } }; ","date":"Sep 26, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/09/26/","section":"LeetCode Solutions","summary":"","title":"LeetCode 371: Sum of Two Integers","type":"leetcode"},{"content":" Foreword # This year\u0026rsquo;s performance was pretty good. Let us do even better next time! I finished Problems 2 and 4 in 30 minutes, while my teammates finished Problems 1 and 3 in a little over an hour. After that came several hours when we had no idea what to do\u0026hellip;\nLet us try not to end up in this situation again.\nProblem 1: Opening Ceremony Fireworks # 1.1 Problem Statement # The opening ceremony of the LeetCode Challenge has begun, and a giant tree-shaped firework has bloomed in the sky. Given a binary tree root representing the firework, the value of each node represents the color at that position of the giant firework. Help Xiao Kou calculate how many distinct colors appear in the giant firework. Example 1: Input: root = [1,3,2,1,null,2] Output: 3 Explanation: There are 3 distinct colors in the firework, with values 1, 2, and 3.\nExample 2: Input: root = [3,3,3] Output: 1 Explanation: Only 1 color appears in the firework, with value 3.\nConstraints: 1 \u0026lt;= number of nodes \u0026lt;= 1000 1 \u0026lt;= Node.val \u0026lt;= 1000 1.2 Analysis # Store the states in a dp array. Whenever a value has not appeared before, increment the count once.\n1.3 Code # /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: bool dp[1005]; int count = 0; void deal(TreeNode * root) { if (!root) return ; if (!dp[root-\u0026gt;val]) { count++; dp[root-\u0026gt;val] = true; } deal(root-\u0026gt;left); deal(root-\u0026gt;right); } int numColor(TreeNode* root) { deal(root); return count; } }; Problem 2: Bicycle Stunt Arena # 2.1 Problem Statement # In the N*M-sized bicycle stunt arena of the LeetCode Challenge, the terrain consists of continuous ups and downs. The terrain heights are recorded in the two-dimensional array terrain, and the deceleration values are recorded in the two-dimensional array obstacle. If a contestant rides from a position with height h1 and deceleration value o1 to an adjacent position with height h2 and deceleration value o2 (in one of the four directions: up, down, left, or right), the change in speed is h1-h2-o2 (a negative value slows the contestant down, while a positive value speeds the contestant up). The contestant starts at coordinate position with an initial speed of 1. Which other positions can the contestant reach while still having speed 1? Return these positions as a two-dimensional array. If there are multiple positions, sort them by row coordinate in ascending order; when the row coordinates are equal, sort by column coordinate in ascending order. Note: The speed cannot be zero or negative during the ride. Example 1: Input: position = [0,0], terrain = [[0,0],[0,0]], obstacle = [[0,0],[0,0]] Output: [[0,1],[1,0],[1,1]] Explanation: Because the current terrain is flat, the rules above let the contestant start at [0,0] and reach every other position with speed 1. Example 2: Input: position = [1,1], terrain = [[5,0],[0,6]], obstacle = [[0,6],[7,0]] Output: [[0,1]] Explanation: Starting from [1,1], the contestant has exactly speed 1 upon reaching [0,1]. Constraints: n == terrain.length == obstacle.length m == terrain[i].length == obstacle[i].length 1 \u0026lt;= n \u0026lt;= 100 1 \u0026lt;= m \u0026lt;= 100 0 \u0026lt;= terrain[i][j], obstacle[i][j] \u0026lt;= 100 position.length == 2 0 \u0026lt;= position[0] \u0026lt; n 0 \u0026lt;= position[1] \u0026lt; m 2.2 Analysis # This is a relatively basic depth-first-search problem. Memoization may be needed to remove duplicate states.\nAfter reading the problem carefully, we can see that arriving at a position does not necessarily imply the same speed every time. Different paths to the same position may produce different speeds.\nTherefore, we must record the state. If we reach the same position twice with the same speed, we do not need to continue from it again. Without this check, a cycle can occur, as in Example 1; failing to remove duplicates would lead to an infinite loop.\nIn summary, the approach is DFS plus memoization for duplicate-state elimination (pruning). The pruning condition is met only when the same position is reached with the same speed.\nThe code is mainly divided into a main function and a DFS function. The DFS function accepts three parameters: the current x and y coordinates and the current speed. When passed[x][y][speed] is true, the same position has already been traversed at the same speed, so there is no need to traverse it again. When res[x][y] is true, the coordinate is a candidate answer. We then traverse the four directions in the usual way, stopping when the speed is less than 0 and so on.\nThe main function handles the input and output, stores some global variables, and performs a simple conversion of res into the required answer format.\n2.3 C++ Code # using VI = vector\u0026lt;int\u0026gt;; using VVI = vector\u0026lt;VI\u0026gt;; const VI direc = {0, 1, 0, -1, 0}; class Solution { public: VVI t, o; bool res[100][100] = {}; bool passed[100][100][105] = {}; int n, m; void dfs(int x, int y, int speed) { if (speed == 1) res[x][y] = true; if (speed \u0026lt; 1) return; if (passed[x][y][speed]) { return; } passed[x][y][speed] = true; for (int i = 0; i \u0026lt; 4; ++i) { int xt = x + direc[i]; int yt = y + direc[i + 1]; if (xt \u0026gt;= 0 \u0026amp;\u0026amp; yt \u0026gt;= 0 \u0026amp;\u0026amp; xt \u0026lt; n \u0026amp;\u0026amp; yt \u0026lt; m) dfs(xt, yt, speed + t[x][y] - t[xt][yt] - o[xt][yt]); } } VVI bicycleYard(VI\u0026amp; p, VVI\u0026amp; terrain, VVI\u0026amp; obstacle) { t = terrain; o = obstacle; n = t.size(); m = t[0].size(); int x = p[0], y = p[1]; dfs(x, y, 1); VVI res_v; res[x][y] = false; for (int i = 0; i \u0026lt; 100; ++i) for (int j = 0; j \u0026lt; 100; ++j) if (res[i][j]) res_v.push_back({i, j}); return res_v; } }; Problem 3: Volunteer Deployment # 3.1 Problem Statement # The LeetCode Challenge has n competition venues (venue IDs start at 0). The distribution of channels between venues is recorded in the two-dimensional array edges, where edges[i]= [x, y] means that channel i connects venue x and venue y (that is, the two venues are adjacent). Initially, each venue has a certain number of volunteers, and the numbers may differ between venues. Over the next m days, the volunteer counts are adjusted each day according to the event's popularity. There are three possible adjustment operations: Halve the number of volunteers in the venue numbered idx. Add the number of volunteers in venue idx to the volunteer count of every venue adjacent to venue idx. Subtract the number of volunteers in venue idx from the volunteer count of every venue adjacent to venue idx. All adjustment information is recorded in the array plans, where plans[i] = [num,idx] means that on day i, adjustment plan num was applied to venue idx . During the post-event review, the final volunteer count of venue 0 was accidentally lost. We retained only the initial total number of volunteers across all venues, totalNum, and a one-dimensional array finalCnt containing the final volunteer counts of venues 1 ~ n-1 . Use the available information to calculate the initial volunteer count of every venue, and return the list in venue-number order. Note: The test data guarantees that a venue's volunteer count is even whenever the first adjustment is applied to it. The test data guarantees that the volunteer count of every neighboring venue is non-negative whenever the third adjustment is applied. The test data guarantees that no venue has more than 10^9 volunteers when the competition begins. The test data guarantees that the given road network contains no self-loops or parallel edges. Example 1: Input: finalCnt = [1,16], totalNum = 21, edges = [[0,1],[1,2]], plans = [[2,1],[1,0],[3,0]] Output: [5,7,9] Explanation: Example 2: Input: finalCnt = [4,13,4,3,8], totalNum = 54, edges = [[0,3],[1,3],[4,3],[2,3],[2,5]], plans = [[1,1],[3,3],[2,5],[1,0]] Output: [10,16,9,4,7,8] Constraints: 2 \u0026lt;= n \u0026lt;= 5*10^4 1 \u0026lt;= edges.length \u0026lt;= min((n * (n - 1)) / 2, 5*10^4) 0 \u0026lt;= edges[i][0], edges[i][1] \u0026lt; n 1 \u0026lt;= plans.length \u0026lt;= 10 1 \u0026lt;= plans[i][0] \u0026lt;=3 0 \u0026lt;= plans[i][1] \u0026lt; n finalCnt.length = n-1 0 \u0026lt;= finalCnt[i] \u0026lt; 10^9 0 \u0026lt;= totalNum \u0026lt; 5*10^13 3.2 Analysis # There is only one unknown value: the number of volunteers in venue 0 at the current (final) time.\nIt is not difficult to see that all three operations are linear operations, and we know the exact operation performed at every step. Therefore, if we know the number of volunteers in venue 0 at the final time, we can reverse the process precisely back to the first step. At that point, the total number of volunteers must equal totalNum exactly.\nLet x denote the number of volunteers in venue 0 at the final time. We can reason backwards. After reversing the process to the first step, the count in every venue is a linear function of x. Their sum is also a linear function, and this sum must equal totalNum. Substituting totalNum into that equation gives x; substituting x into each venue\u0026rsquo;s expression then gives its initial volunteer count.\nIn the implementation, the two arrays x_param and c_param represent the coefficient of x and the constant term of each venue\u0026rsquo;s linear function. After reversing all plans, compute x_param_sum and c_param_sum. The equation for x is:\n$$ \\sum^{n}_{i=1}{x_{param}[i]} * x + \\sum^{n}_{i=1}{c_{param}[i]} = totalNum $$After a simple rearrangement:\n$$ x = \\frac{(totalNum - \\sum^{n}_{i=1}{c_{param}[i]})}{\\sum^{n}_{i=1}{x_{param}[i]}} $$Finally, substitute x into each expression to complete the calculation.\n3.3 C++ Code # using VI = vector\u0026lt;int\u0026gt;; using VVI = vector\u0026lt;VI\u0026gt;; using ll = long long; class Solution { public: VI volunteerDeployment(VI\u0026amp; finalCnt, ll totalNum, VVI\u0026amp; edges, VVI\u0026amp; plans) { VI m[50005]; int n = finalCnt.size() + 1; // x系数和常数 int x_param[50005] = {}, c_param[50005] = {}; for (auto \u0026amp; edge : edges) { m[edge[0]].push_back(edge[1]); m[edge[1]].push_back(edge[0]); } x_param[0] = 1; for (int i = 0; i \u0026lt; n - 1; ++i) c_param[i + 1] = finalCnt[i]; while (plans.size()) { int kind = plans.back()[0]; int place = plans.back()[1]; plans.pop_back(); if (kind == 1) { x_param[place] *= 2; c_param[place] *= 2; } else if (kind == 2) { for (auto \u0026amp; nxt : m[place]) { x_param[nxt] -= x_param[place]; c_param[nxt] -= c_param[place]; } } else { for (auto \u0026amp; nxt : m[place]) { x_param[nxt] += x_param[place]; c_param[nxt] += c_param[place]; } } } ll x_param_sum = 0, c_param_sum = 0; for (int i = 0; i \u0026lt; n; ++i) { x_param_sum += x_param[i]; c_param_sum += c_param[i]; } // 方程: x_param_sum * x + c_param_sum = totalNum int x = (totalNum - c_param_sum) / x_param_sum; vector\u0026lt;int\u0026gt; res(n); for (int i = 0; i \u0026lt; n; ++i) res[i] = x_param[i] * x + c_param[i]; return res; } }; Problem 4: Entry Security Check # 4.1 Problem Statement # The entry ceremony of the LeetCode Challenge is about to begin. For security reasons, N security rooms have been set up, with a total capacity of M; capacities[i] records the capacity of security room i. There are two types of security rooms: First in, first out: among all spectators in the room, the spectator who entered earliest leaves first. Last in, first out: among all spectators in the room, the spectator who entered most recently leaves first. Exactly M+1 spectators (numbered from 0) need to queue to pass through security in order. The rules are: A spectator must first enter security room 0. When a spectator enters security room i (0 \u0026lt;= i \u0026lt; N ), If the room has not reached its capacity, the spectator may enter directly. If the room has reached capacity, one spectator must leave according to the room type before the new spectator can enter. When a spectator leaves security room i (0 \u0026lt;= i \u0026lt; N-1 ), they enter security room i+1 for the next security check. If the type of each security room can be chosen arbitrarily, how many assignments make spectator k the first spectator to pass through the final security room and enter? Note: Spectators cannot leave a security room voluntarily. A spectator can leave only when the room is full and a new spectator needs to enter; the room type then determines who leaves. Since the number of assignments may be large, return the answer modulo 1000000007. Example 1: Input: capacities = [2,2,3], k = 2 Output: 2 Explanation: There are 2 valid assignments: Assignment 1: set rooms 0 and 1 to last-in, first-out, and room 2 to first-in, first-out. Assignment 2: set rooms 0 and 1 to first-in, first-out, and room 2 to last-in, first-out. The following is an illustration of Assignment 1: Example 2: Input: capacities = [3,3], k = 3 Output: 0 Example 3: Input: capacities = [4,3,2,2], k = 6 Output: 2 Constraints: 1 \u0026lt;= capacities.length \u0026lt;= 200 1 \u0026lt;= capacities[i] \u0026lt;= 200 0 \u0026lt;= k \u0026lt;= sum(capacities) 4.2 Analysis # Observe that first-in, first-out corresponds to a queue, while last-in, first-out corresponds to a stack.\nLooking at the second GIF, when a container (which we will also call a room) is a queue, the first person to enter is the first person to leave. Thus, a queue has no effect on the first person in the process. In contrast, consider a stack: a stack of length 2 must first be filled with one element, and that element is fixed in place and cannot move. Therefore, for the first person in the process, a stack of length c can intercept c-1 people.\nThe rest is simple. To make person k reach the front, we must use stacks to intercept the first k people.\nWe can therefore rewrite the problem in a familiar form:\n有`N`个硬币，每个的金额都在`cap`数组中给出（需要一个减 1 操作）。我们从前往后选，求最终金额为`k`的方案数。 Does it look much simpler now?\nThe final solution is a straightforward dynamic program. Because each coin can be used only once, the direction in which we update dp must be controlled.\n4.3 C++ Code # const int md = 1000000007; class Solution { public: int securityCheck(vector\u0026lt;int\u0026gt;\u0026amp; cap, int k) { for (auto \u0026amp; c : cap) c--; int sum = accumulate(cap.begin(), cap.end(), 0); if (sum \u0026lt; k) return 0; int dp[40005] = {1}; for (auto \u0026amp; c : cap) { for (int i = k - c; i \u0026gt;= 0; --i) { (dp[i + c] += dp[i]) %= md; } } return dp[k]; } }; ","date":"Sep 25, 2021","externalUrl":null,"permalink":"/en/leetcode/special/leetcode-cup-2021-autumn-group/","section":"LeetCode Solutions","summary":"","title":"2021 LeetCode Autumn Team Competition Review","type":"leetcode"},{"content":"","date":"Sep 25, 2021","externalUrl":null,"permalink":"/en/tags/contest/","section":"Tags","summary":"","title":"Contest","type":"tags"},{"content":"Given two words\u0026nbsp;word1\u0026nbsp;and\u0026nbsp;word2, find the minimum number of steps required to make\u0026nbsp;word1\u0026nbsp;and\u0026nbsp;word2the same, where each step deletes one character from either string.\n\u0026nbsp;\nExample:\nInput: \"sea\", \"eat\" Output: 2 Explanation: In the first step, change \"sea\" to \"ea\"; in the second step, change \"eat\" to \"ea\" \u0026nbsp;\nConstraints:\nThe length of each given word does not exceed 500. The characters in each given word are lowercase English letters. Approach # Problems involving two strings and an edit-distance-like operation are generally straightforward to solve with two-dimensional dynamic programming.\nThere are two ways to think about this problem, both using dynamic programming: a forward perspective and a backward perspective.\nForward Perspective # dp[i][j] represents the answer: the minimum number of deletion operations needed for the string formed by the first i characters of word1 and the first j characters of word2.\nThe boundary conditions are dp[i][0]=i(i \u0026lt;= word1.length) and dp[0][i]=i(i \u0026lt;= word2.length). An empty string and a string of length i can only become equal by deleting all i characters from the non-empty string, so the boundary conditions follow directly.\nThe dynamic-programming transitions are:\ndp[i + 1][j + 1] = dp[i][j] (a[i] == b[j]) dp[i + 1][j + 1] = min(dp[i + 1][j], dp[i][j + 1]) + 1 (a[i] != b[i]) In the first case, when the two characters are equal, the deletion distance does not increase.\nThe second case is also easy to understand. If the current characters cannot be matched, we must delete one character and then continue comparing, so we take the smaller value and add 1.\nBackward Perspective # Since the operation deletes some characters from the strings, what should we call the common part that remains? On closer inspection, it is the longest common subsequence.\nWe can first find the length of the longest common subsequence of the two strings, then subtract twice that length from the sum of the two string lengths. The result is the total number of characters that must be removed from both strings.\nThe boundary conditions are dp[i][0]=0 and dp[0][i]=0.\nThe dynamic-programming transitions are:\ndp[i + 1][j + 1] = dp[i][j] + 1 (a[i] == b[j]) dp[i + 1][j + 1] = max(dp[i + 1][j], dp[i][j + 1]) (a[i] != b[i]) These transitions are also straightforward to understand.\nC++ Code (Forward) # #define REP(i, j) for (int i = 0; i \u0026lt; j; ++i) class Solution { public: int minDistance(string a, string b) { int m = a.size(), n = b.size(); int dp[m + 1][n + 1]; memset(dp, 0, sizeof dp); REP(i, m) REP(j, n) if (a[i] == b[j]) dp[i + 1][j + 1] = dp[i][j] + 1; else dp[i + 1][j + 1] = max(dp[i + 1][j], dp[i][j + 1]); return m + n - 2 * dp[m][n]; } }; C++ Code (Backward) # #define REP(i, j) for (int i = 0; i \u0026lt; j; ++i) class Solution { public: int minDistance(string a, string b) { /*这破烂玩意不用dp做我把力扣炸了*/ int m = a.size(), n = b.size(); int dp[m + 1][n + 1]; memset(dp, 0, sizeof dp); REP(i, m) REP(j, n) if (a[i] == b[j]) dp[i + 1][j + 1] = dp[i][j] + 1; else dp[i + 1][j + 1] = max(dp[i + 1][j], dp[i][j + 1]); return m + n - 2 * dp[m][n]; } }; ","date":"Sep 25, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/09/25/","section":"LeetCode Solutions","summary":"","title":"LeetCode 583: Delete Operation for Two Strings","type":"leetcode"},{"content":"Given an integer, write a function to determine whether it is a power of 3. Return true if it is; otherwise, return false.\nAn integer n is a power of 3 if there exists an integer x such that n == 3x.\n\u0026nbsp;\nExample 1:\nInput:n = 27 Output:true Example 2:\nInput:n = 0 Output:false Example 3:\nInput:n = 9 Output:true Example 4:\nInput:n = 45 Output:false \u0026nbsp;\nConstraints:\n-231 \u0026lt;= n \u0026lt;= 231 - 1 \u0026nbsp;\nFollow-up:\nCan you solve this problem without using loops or recursion? Approach # This problem is actually simple, whether or not recursion is used.\nRecursion follows the usual idea: keep dividing by 3. If the result is exactly 1, the number is a power of 3; if anything else remains, it is not.\nThe non-recursive approach is also conventional. Powers have the property that their factors include every smaller (or equal) power of 3. Therefore, we only need to choose the largest possible power of 3, N, within the 32-bit integer range (1162261467), and determine whether the given number is a factor of N. If it is, it must be a power of 3.\nRust Code # # struct Solution; impl Solution { pub fn is_power_of_three(n: i32) -\u0026gt; bool { if n % 3 == 0 \u0026amp;\u0026amp; n != 0 { Self::is_power_of_three(n / 3) } else { n == 1 } } } C++ Code # class Solution { public: bool isPowerOfThree(int n) { return n \u0026gt; 0 \u0026amp;\u0026amp; 1162261467 % n == 0; } } ","date":"Sep 23, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/09/23/","section":"LeetCode Solutions","summary":"","title":"LeetCode 326: Power of Three","type":"leetcode"},{"content":"Given a list of the friendship preferences of n friends, where n is always even.\nFor each friend i, preferences[i] contains a list of friends ordered from most preferred to least preferred. In other words, a friend appearing earlier in the list is preferred by i over a friend appearing later. Each friend is represented by an integer between 0 and n-1.\nAll friends are split into pairs, given by the list pairs, where pairs[i] = [xi, yi] means that xi is paired with yi, and yi is paired with xi.\nHowever, this pairing may make some friends unhappy. If x is paired with y and u is paired with v, then x is unhappy if both of the following conditions hold:\nx prefers u over y, and u prefers x over v Return the number of unhappy friends.\n\u0026nbsp;\nExample 1:\nInput:n = 4, preferences = [[1, 2, 3], [3, 2, 0], [3, 1, 0], [1, 2, 0]], pairs = [[0, 1], [2, 3]] Output:2 Explanation: Friend 1 is unhappy because: - 1 is paired with 0, but 1 prefers 3 over 0, and - 3 prefers 1 over 2. Friend 3 is unhappy because: - 3 is paired with 2, but 3 prefers 1 over 2, and - 1 prefers 3 over 0. Friends 0 and 2 are happy. Example 2:\nInput:n = 2, preferences = [[1], [0]], pairs = [[1, 0]] Output:0 Explanation:Friends 0 and 1 are both happy. Example 3:\nInput:n = 4, preferences = [[1, 3, 2], [2, 3, 0], [1, 3, 0], [0, 2, 1]], pairs = [[1, 3], [0, 2]] Output:4 \u0026nbsp;\nConstraints:\n2 \u0026lt;= n \u0026lt;= 500 n is even preferences.length\u0026nbsp;== n preferences[i].length\u0026nbsp;== n - 1 0 \u0026lt;= preferences[i][j] \u0026lt;= n - 1 preferences[i] does not contain i All values in preferences[i] are distinct pairs.length\u0026nbsp;== n/2 pairs[i].length\u0026nbsp;== 2 xi != yi 0 \u0026lt;= xi, yi\u0026nbsp;\u0026lt;= n - 1 Every friend is included in exactly one pair Approach # First, preprocess the input. When querying the preference between two people, we want to provide two people and receive a preference score, but the data supplied by the problem is not convenient for that. We can reorganize it into a two-dimensional array.\n# let n = 10; # let preferences = vec![vec![3]]; let n = n as usize; let mut pre = vec![vec![0; n]; n]; for i in 0..n { for j in 0..(n - 1) { pre[i][preferences[i][j] as usize] = n - j - 1; } } The code above reorganizes preferences into pre. We can then query it conveniently with pre[i][j].\nNext, carefully observe the unhappy condition in the example and rewrite it as code: pre[x][u] \u0026gt; pre[x][y] \u0026amp;\u0026amp; pre[u][x] \u0026gt; pre[u][v] This expression is interesting. When it holds, not only is x unhappy, but u is unhappy as well.\nLooking further, we can see that this expression is completely determined by x and u. Therefore, among the four variables x,y,u,v, there are four such pairs of combinations.\n# let (a, b, c, d) = (0, 0, 0, 0); # let pre = vec![vec![3]]; # let mut set = std::collections::HashSet::new(); if pre[a][c] \u0026gt; pre[a][b] \u0026amp;\u0026amp; pre[c][a] \u0026gt; pre[c][d] { set.insert(a); set.insert(c); } if pre[b][c] \u0026gt; pre[b][a] \u0026amp;\u0026amp; pre[c][b] \u0026gt; pre[c][d] { set.insert(b); set.insert(c); } if pre[b][d] \u0026gt; pre[b][a] \u0026amp;\u0026amp; pre[d][b] \u0026gt; pre[d][c] { set.insert(b); set.insert(d); } if pre[d][a] \u0026gt; pre[d][c] \u0026amp;\u0026amp; pre[a][d] \u0026gt; pre[a][b] { set.insert(d); set.insert(a); } Here, set is a hash set used to avoid duplicates. (x,y,u,v are written as a,b,c,d for convenience.)\nFinally, iterate over the hash set and return its size.\nRust Code # # struct Solution; impl Solution { pub fn unhappy_friends(n: i32, preferences: Vec\u0026lt;Vec\u0026lt;i32\u0026gt;\u0026gt;, pairs: Vec\u0026lt;Vec\u0026lt;i32\u0026gt;\u0026gt;) -\u0026gt; i32 { let n = n as usize; let mut pre = vec![vec![0; n]; n]; for i in 0..n { for j in 0..(n - 1) { pre[i][preferences[i][j] as usize] = n - j - 1; } } // println!(\u0026#34;{:?}\u0026#34;, pre); use std::collections::*; let mut set = HashSet::new(); for i in 0..pairs.len() { for j in 0..pairs.len() { let a = pairs[i][0] as usize; let b = pairs[i][1] as usize; let c = pairs[j][0] as usize; let d = pairs[j][1] as usize; if pre[a][c] \u0026gt; pre[a][b] \u0026amp;\u0026amp; pre[c][a] \u0026gt; pre[c][d] { set.insert(a); set.insert(c); } if pre[b][c] \u0026gt; pre[b][a] \u0026amp;\u0026amp; pre[c][b] \u0026gt; pre[c][d] { set.insert(b); set.insert(c); } if pre[b][d] \u0026gt; pre[b][a] \u0026amp;\u0026amp; pre[d][b] \u0026gt; pre[d][c] { set.insert(b); set.insert(d); } if pre[d][a] \u0026gt; pre[d][c] \u0026amp;\u0026amp; pre[a][d] \u0026gt; pre[a][b] { set.insert(d); set.insert(a); } } } set.len() as i32 } } ","date":"Aug 14, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/08/14/","section":"LeetCode Solutions","summary":"","title":"LeetCode 1583: Count Unhappy Friends","type":"leetcode"},{"content":"","date":"Aug 14, 2021","externalUrl":null,"permalink":"/en/tags/simulation/","section":"Tags","summary":"","title":"Simulation","type":"tags"},{"content":"Given an integer n, count the number of occurrences of the digit 1 in all non-negative integers less than or equal to n.\n\u0026nbsp;\nExample 1:\nInput:n = 13 Output:6 Example 2:\nInput:n = 0 Output:0 \u0026nbsp;\nConstraints:\n0 \u0026lt;= n \u0026lt;= 2 * 109 Approach # 令a=n/i,b=n%i; 举例分析，假设n=12345，i=100; 此时a=123,b=45： 1）当a的个位大于1时（也就是n的百位），百位为1的数总共出现了(a/10+1)*100次 2）当a为1的时候，百位为1的数总共出现了(a/10)*100+(b+1); 3）当a为0的时候，百位为1的数出现了(a/10)*100次； 因此可以根据a的个位是否为1分成2中情况计算，可以使用一个表达式合并以上三个式子。 a. 9=\u0026gt;(a个位)\u0026gt;=2和0=\u0026lt;(a个位\u0026lt;=1)时的(a/10+1),(a/10)表达式与(a+8)/10等价； b. （a\u0026gt;=2时（a+8）/10的结果与a/10+1相同，a==1或a==0时（a+8）/10的结果等价a/10。 c. 当a个位为1时需要加上（b+1）与(a%10==1)*(b+1)等价。因此合并后百位为1的数的个数为 (a+8)/10*i+(a%10==1)*(b+1); 然后令i从个位到最高位遍历即可计算每一位含1的个数； Rust Code # # struct Solution; impl Solution { pub fn count_digit_one(n: i32) -\u0026gt; i32 { let mut cnt = 0; let mut i = 1; while i \u0026lt;= n { let a = n / i; let b = n % i; cnt += (a + 8) / 10 * i + if a % 10 == 1 {b + 1} else {0}; i *= 10; } cnt } } ","date":"Aug 13, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/08/13/","section":"LeetCode Solutions","summary":"","title":"LeetCode 233: Number of Digit One","type":"leetcode"},{"content":"Given a string s, find the longest palindromic subsequence and return its length.\nA subsequence is a sequence formed by deleting some characters, or none, without changing the order of the remaining characters.\n\u0026nbsp;\nExample 1:\nInput:s = \"bbbab\" Output:4 Explanation:One possible longest palindromic subsequence is \"bbbb\". Example 2:\nInput:s = \"cbbd\" Output:2 Explanation:One possible longest palindromic subsequence is \"bb\". \u0026nbsp;\nConstraints:\n1 \u0026lt;= s.length \u0026lt;= 1000 s consists only of lowercase English letters Approach # There is one particularly important observation:\nThe longest palindromic subsequence of string s is equivalent to the longest common subsequence of string s and its reverse s\u0026rsquo;.\nTo see why, any longest common subsequence of s and its reverse is a palindrome: it appears in the forward direction and in the reverse direction, and both are identical, which is the definition of a palindrome.\nThere also cannot be a palindromic subsequence longer than the longest common subsequence of s and its reverse. If there were one, the longest common subsequence of s and its reverse would be longer as well.\nThus, we have successfully transformed the problem into finding the length of the longest common subsequence of s and its reverse.\nThis makes the problem convenient to solve with two-dimensional dynamic programming. We first define the dynamic-programming table dp[n+1][n+1], reserving one extra row and column to simplify the calculation.\nThe meaning of dp[i][j] is the length of the longest common subsequence of the first i characters of s and the first j characters of s\u0026rsquo;.\nThe recurrence is also straightforward. When the two characters are equal, dp[i][j] = dp[i - 1][j - 1] + 1; otherwise, dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]).\nRust Code # # struct Solution; impl Solution { pub fn longest_palindrome_subseq(s: String) -\u0026gt; i32 { let s = s.into_bytes(); let n = s.len(); let mut res = 0; let mut dp = vec![vec![0; n + 1]; n + 1]; for i in 1..=n { for j in 1..=n { if s[n - i] == s[j - 1] { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j] = dp[i - 1][j].max(dp[i][j - 1]); } } } dp[n][n] } } ","date":"Aug 12, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/08/12/","section":"LeetCode Solutions","summary":"","title":"LeetCode 516: Longest Palindromic Subsequence","type":"leetcode"},{"content":"Given an integer array nums, return the number of arithmetic subsequences in nums.\nA sequence is called an arithmetic sequence if it contains at least three elements and the difference between every pair of adjacent elements is the same.\nFor example, [1, 3, 5, 7, 9], [7, 7, 7, 7], and [3, -1, -5, -9] are all arithmetic sequences. However, [1, 1, 2, 5, 7] is not an arithmetic sequence. A subsequence of an array is a sequence obtained by deleting some elements from the array, possibly none.\nFor example, [2,5,10] is a subsequence of [1,2,1,2,4,1,5,10]. The input guarantees that the answer is a 32-bit integer.\n\u0026nbsp;\nExample 1:\nInput:nums = [2,4,6,8,10] Output:7 Explanation:All arithmetic subsequences are: [2,4,6] [4,6,8] [6,8,10] [2,4,6,8] [4,6,8,10] [2,4,6,8,10] [2,6,10] Example 2:\nInput:nums = [7,7,7,7,7] Output:16 Explanation:Every subsequence of the array is an arithmetic subsequence. \u0026nbsp;\nConstraints:\n1\u0026nbsp; \u0026lt;= nums.length \u0026lt;= 1000 -231 \u0026lt;= nums[i] \u0026lt;= 231 - 1 Approach # This problem is almost identical to yesterday\u0026rsquo;s problem. The only difference is that a subarray has been changed to a subsequence.\nHowever, this is a significant change: almost none of our previous reasoning is useful here.\nA subsequence is not contiguous. In other words, any numbers that appear in order but are not necessarily adjacent form a valid arithmetic subsequence as long as their differences are constant.\nWe must understand the problem before we can solve it.\nFor subsequences, is there any approach other than brute force? The answer is actually simple: we only need to extract a reusable pattern.\nFor example, if we know that [\u0026hellip;..,2,4,6] is an arithmetic sequence, then how many elements appear before 4 is irrelevant to us. For later numbers, we do not care how many elements occur before 2, because all of them form arithmetic sequences with a difference of 2.\nThe outline of the data structure now emerges. The outer layer traverses the array from left to right, and at every step records information about the current element and the preceding elements for later use.\nThis information must be recorded based on the difference of the arithmetic sequence, so we use a HashMap\u0026lt;i32,?\u0026gt;. What should its values contain? For later use, we need to record the counts, specifically the number of valid arithmetic subsequences, but this introduces the issue of sequence length.\nLength is crucial. If we record sequences of length 2, we may count too many; yet we cannot record only sequences of length at least 3, because those must be derived from sequences of length 2.\nIn this situation, we use a HashMap\u0026lt;i32, (i32, i32)\u0026gt;. The first i32 records sequences with length at least 3, while the second records sequences with length exactly 2.\nThere is another pitfall to note, which I believe many people miss: -231 \u0026lt;= nums[i] \u0026lt;= 231 - 1 This condition means that calculating the difference between two values requires a type wider than i32, otherwise it may overflow. We therefore use i64 instead.\nThis gives us the first version of the code:\nimpl Solution { pub fn number_of_arithmetic_slices(nums: Vec\u0026lt;i32\u0026gt;) -\u0026gt; i32 { use std::collections::*; let mut dp: Vec\u0026lt;HashMap\u0026lt;i64, (i32, i32)\u0026gt;\u0026gt; = vec![]; let n = nums.len(); let mut res = 0; for i in 0..n { let mut nxt = HashMap::new(); for j in 0..i { let diff = nums[i] as i64 - nums[j] as i64; if let Some(value) = dp[j].get(\u0026amp;diff) { nxt.entry(diff).or_insert((0, 0)).0 += value.0 + value.1; res += value.0 + value.1; } nxt.entry(diff).or_insert((0, 0)).1 += 1; } dp.push(nxt); } res } } dp is the aggregate of all information for every position. We record all data while traversing nums.\nnxt.entry(diff).or_insert((0, 0)).1 += 1; This means that every nums[j] before position i can form a length-2 combination with nums[i], so it is added to the later position.\nnxt.entry(diff).or_insert((0, 0)).0 += value.0 + value.1; This means that if a sequence of length greater than 3 or exactly 2 has appeared before position j, combining it with nums[i] necessarily produces a subsequence of length at least 3. We add it to the preceding position and to the answer.\nThis code passes, but notice one key point. When using (i32, i32), we always use their sum. The only expression that appears in the code is value[0] + value[1]. Can we merge the two values?\nYes. After merging them, HashMap\u0026lt;i64, i32\u0026gt; represents the number of all subsequences of length at least 2 for a particular diff. Surprisingly, this does not affect the calculation.\nRust Code # impl Solution { pub fn number_of_arithmetic_slices(nums: Vec\u0026lt;i32\u0026gt;) -\u0026gt; i32 { use std::collections::*; let mut dp: Vec\u0026lt;HashMap\u0026lt;i64, i32\u0026gt;\u0026gt; = vec![]; let n = nums.len(); let mut res = 0; for i in 0..n { let mut nxt = HashMap::new(); for j in 0..i { let diff = nums[i] as i64 - nums[j] as i64; if let Some(value) = dp[j].get(\u0026amp;diff) { *nxt.entry(diff).or_insert(0) += value; res += value; } *nxt.entry(diff).or_insert(0) += 1; } dp.push(nxt); } res } } Do you see it? The answer is obtained by adding the length-2 subsequences from the previous position; after adding the current element, they necessarily become sequences of length at least 3, so our concern was unnecessary! 😂\n","date":"Aug 11, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/08/11/","section":"LeetCode Solutions","summary":"","title":"LeetCode 446: Arithmetic Slices II - Subsequence","type":"leetcode"},{"content":"If a sequence has at least three elements and the difference between every pair of adjacent elements is the same, it is called an arithmetic sequence.\nFor example, [1,3,5,7,9], [7,7,7,7], and [3,-1,-5,-9] are all arithmetic sequences. Given an integer array nums, return the number of subarrays of nums that are arithmetic.\nA subarray is a contiguous sequence within an array.\n\u0026nbsp;\nExample 1:\nInput:nums = [1,2,3,4] Output:3 Explanation:There are three arithmetic subarrays in nums: [1, 2, 3], [2, 3, 4], and [1,2,3,4] itself. Example 2:\nInput:nums = [1] Output:0 \u0026nbsp;\nConstraints:\n1 \u0026lt;= nums.length \u0026lt;= 5000 -1000 \u0026lt;= nums[i] \u0026lt;= 1000 Approach # A subarray must be contiguous within the original array, so we only need to consider the differences between each pair of adjacent elements. We can preprocess these differences in a new array.\nFirst, consider what is required to form an arithmetic sequence. The answer is exactly what the definition says: the differences must be equal. What should we do when several consecutive differences are equal?\nAs the examples show, when multiple consecutive differences are equal, the choices resemble a combination problem. Both [1,2,3,4] and [1,2,3], [2,3,4] are valid answers. If four consecutive numbers (that is, three consecutive gaps) have the same difference, there are three possibilities. What if there are n numbers in a row?\n1.先假设存在n个可以构成等差数列的数字 例如：1,2,3,4,5,6,7,.....,n（刚好n个） 2.因为最短需要长度为3的子数组，所以长度为3的有n - 2个 3.长度为t的子数组（t\u0026lt;n）有n - t + 1个 4.总共有(n-2)+(n-3)+....+(1)个 还是4.所以总共有(n-2)*(n-1)/2个 However, it is difficult to determine which numbers belong to the same arithmetic sequence, and some elements may be shared across overlapping sequences. For example, in [1,2,3,2,1], the 3 can be shared by two subarrays.\nWe can therefore work with the gaps. First calculate the pairwise differences, or gaps, and then compare them. Transforming [1,2,3,2,1] gives [1,1,-1,-1]; whenever two consecutive gaps are equal, we know they can form a subarray. This also handles shared elements elegantly.\nThe approach is now clear. We only need to traverse the array once and focus on the gaps. When equal gaps occur consecutively, count them; if there are at most n consecutive gaps, add n*(n-1) to the answer.\nRust Code # # struct Solution; impl Solution { pub fn number_of_arithmetic_slices(nums: Vec\u0026lt;i32\u0026gt;) -\u0026gt; i32 { let n = nums.len(); let mut res = 0; let mut pre = i32::MAX; let mut count = 0; for i in 1..n { let item = nums[i] - nums[i - 1]; if pre != item { if count \u0026gt; 1 { res += count * (count - 1) / 2; } pre = item; count = 1; } else { count += 1; } } if count \u0026gt; 1 { res += count * (count - 1) / 2; } res } } ","date":"Aug 10, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/08/10/","section":"LeetCode Solutions","summary":"","title":"LeetCode 413: Arithmetic Slices","type":"leetcode"},{"content":" A super ugly number is a positive integer whose every prime factor appears in the prime array primes.\nGiven an integer n and an integer array primes, return the n-th super ugly number.\nThe input guarantees that the n-th super ugly number is within the range of a signed 32-bit integer.\n\u0026nbsp;\nExample 1:\nInput:n = 12, primes = [2,7,13,19] Output:32 Explanation:Given the prime array of length 4, primes = [2,7,13,19], the first 12 super ugly numbers are: [1,2,4,7,8,13,14,16,19,26,28,32]. Example 2:\nInput:n = 1, primes = [2,3,5] Output:1 Explanation:1 has no prime factors, so all of its prime factors are in the prime array primes = [2,3,5]. Constraints:\n1 \u0026lt;= n \u0026lt;= 106 1 \u0026lt;= primes.length \u0026lt;= 100 2 \u0026lt;= primes[i] \u0026lt;= 1000 The input guarantees that primes[i] is prime All values in primes are distinct and sorted in ascending order Approach # The problem is relatively straightforward: we need to generate a list containing all super ugly numbers, and we only care about the n-th one.\nThere are several ways to build this list. A common approach uses a priority queue.\nA priority queue is a special data structure that keeps all of its elements ordered. We can therefore maintain a priority queue whose initial value is [1], and perform the following operations n times:\n1.在第n次的时候，从优先队列中取出一个最小的数字t 2.t即为第n个超级丑数 3.将t * primes[0], t * primes[1], .....等数字放入优先队列中。 4.这样就能保证所有超级丑数都曾经被加入过该优先队列，而且因为我们是按照从小到大的顺序取的，所以第二条成立 Following this approach, we can compute the n-th super ugly number in \\(O(n * primes.length * log_2(n * primes.length))\\) time.\nRust Code # use std::collections::*; # struct Solution; impl Solution { pub fn nth_super_ugly_number(mut n: i32, primes: Vec\u0026lt;i32\u0026gt;) -\u0026gt; i32 { let mut set = BTreeSet::new(); set.insert(1); while set.len() \u0026gt; 0 { let first = *set.iter().next().unwrap(); set.remove(\u0026amp;first); for \u0026amp;prime in \u0026amp;primes { if (first as i64) * (prime as i64) \u0026lt; (i32::MAX as i64) { set.insert(first * prime); } } n -= 1; if n == 0 { return first; } } 0 } } An Advanced Method # Approach # It is not difficult to see that every term in the super ugly number sequence can be represented as the product of a number in primes and a super ugly number that appeared earlier.\nAfter understanding the previous method, we can also see that at every step we take out a super ugly number, multiply it by a number in primes, and put the result back into the super ugly number sequence as a candidate.\nHowever, this produces many redundant and unnecessary calculations. For example, the sequence of super ugly numbers may be very long even though we only need its first few terms. This motivates us to find a new way to calculate it.\nWe therefore create a new array called pointer. Each of its entries corresponds to one entry in primes, and all entries initially equal 0. We also need to record the ugly numbers in a sequence named dp.\nIn each iteration, perform the following steps:\n1.计算出当前最小候选超级丑数的值 2.具体的流程为求 dp[pointer[i]] * primes[i] 的最小值(i的取值范围就是primes的长度m) 3.该数即为下一个超级丑数 dp_nxt 4.对于所有项 dp[pointer[i]] * primes[i] == dp_nxt 的i，均使 pointer[i] 增加1 To review the idea, every super ugly number can be obtained by multiplying a previously seen super ugly number by a number in primes. The current pointer indicates the position of that earlier super ugly number.\nDuplicates can occur. For example, 2*9 and 6*3 both produce 18, which is why pointer must be advanced for every entry that equals the minimum value.\nWith this traversal, we can enumerate every possible super ugly number in ascending order while avoiding many invalid calculations. Following this approach, all calculations can be completed in O(n * primes.length) time.\nuse std::collections::*; # struct Solution; impl Solution { pub fn nth_super_ugly_number(n: i32, primes: Vec\u0026lt;i32\u0026gt;) -\u0026gt; i32 { let mut dp = vec![1]; let n = n as usize; let m = primes.len(); let mut pointer = vec![0; m]; while dp.len() \u0026lt; n { let mut min_pos = 0; for i in 1..m { if dp[pointer[i]] * primes[i] \u0026lt; dp[pointer[min_pos]] * primes[min_pos] { min_pos = i; } } let tmp = dp[pointer[min_pos]] * primes[min_pos]; dp.push(tmp); for i in 0..m { if dp[pointer[i]] * primes[i] == tmp { pointer[i] += 1; } } } println!(\u0026#34;{:?}\u0026#34;, dp); dp[n - 1] } } ","date":"Aug 9, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/08/09/","section":"LeetCode Solutions","summary":"","title":"LeetCode 313: Super Ugly Number","type":"leetcode"},{"content":"The Tribonacci sequence\u0026nbsp;Tn\u0026nbsp;is defined as follows:\u0026nbsp;\nT0 = 0, T1 = 1, T2 = 1, and, when n \u0026gt;= 0,\u0026nbsp;Tn+3 = Tn + Tn+1 + Tn+2\nGiven an integer\u0026nbsp;n, return the value of the n-th Tribonacci number\u0026nbsp;Tn .\n\u0026nbsp;\nExample 1:\nInput:n = 4 Output:4 Explanation: T_3 = 0 + 1 + 1 = 2 T_4 = 1 + 1 + 2 = 4 Example 2:\nInput:n = 25 Output:1389537 \u0026nbsp;\nConstraints:\n0 \u0026lt;= n \u0026lt;= 37 The answer is guaranteed to be a 32-bit integer, that is,\u0026nbsp;answer \u0026lt;= 2^31 - 1. Approach # By inspection, the problem asks us to compute a sequence in which each term is obtained from the previous three terms. Therefore, the simplest brute-force algorithm is sufficient.\nWe create an array with the three fixed values given in the problem, [0,1,1]. We then use the given n to compute terms until reaching the requested position, which gives us the n-th Tribonacci number.\nRust Code # # struct Solution; impl Solution { pub fn tribonacci(n: i32) -\u0026gt; i32 { let n = n as usize; let mut v = vec![0, 1, 1]; let mut cur_len = 3; while cur_len \u0026lt;= n { v.push(v[cur_len - 1] + v[cur_len - 2] + v[cur_len - 3]); cur_len += 1; } v[n] } } Result # # fn main() { # pub fn tribonacci(n: i32) -\u0026gt; i32 { # let n = n as usize; # let mut v = vec![0, 1, 1]; # let mut cur_len = 3; # while cur_len \u0026lt;= n { # v.push(v[cur_len - 1] + v[cur_len - 2] + v[cur_len - 3]); # cur_len += 1; # } # v[n] # } println!(\u0026#34;{:?}\u0026#34;, tribonacci(2)); # } ","date":"Aug 8, 2021","externalUrl":null,"permalink":"/en/leetcode/2021/08/08/","section":"LeetCode Solutions","summary":"","title":"LeetCode 1137: N-th Tribonacci Number","type":"leetcode"},{"content":"","date":"2021年8月1日","externalUrl":null,"permalink":"/tags/archive/","section":"Tags","summary":"","title":"Archive","type":"tags"},{"content":"之前是在蚂蚁笔记上进行写作。但因为诸多问题，将其迁移到GitHub Pages上来进行维护。 如需阅览之前的笔记，请点击下载(共有93篇)\n可能会比较乱，因为没有按照时间加标签，但根据题号还是可以找到指定的题目的。 ","date":"2021年8月1日","externalUrl":null,"permalink":"/leetcode/leanote/","section":"LeetCode 题解","summary":"","title":"关于从蚂蚁笔记迁移而来的说明","type":"leetcode"},{"content":"Background, purpose, and essential information about this technical notebook.\n","date":"Aug 14, 2020","externalUrl":null,"permalink":"/en/about/","section":"About This Site","summary":"","title":"About This Site","type":"about"},{"content":"","date":"Aug 14, 2020","externalUrl":null,"permalink":"/en/tags/hugo/","section":"Tags","summary":"","title":"Hugo","type":"tags"},{"content":"","date":"Aug 14, 2020","externalUrl":null,"permalink":"/en/categories/site/","section":"Categories","summary":"","title":"Site","type":"categories"},{"content":"","date":"Aug 14, 2020","externalUrl":null,"permalink":"/en/tags/website/","section":"Tags","summary":"","title":"Website","type":"tags"},{"content":" Welcome to Dawn Magnet\u0026rsquo;s Site # Welcome to Dawn Magnet\u0026rsquo;s site.\n","date":"Aug 14, 2020","externalUrl":null,"permalink":"/en/about/startup/","section":"About This Site","summary":"","title":"Welcome to Dawn Magnet's Site","type":"about"},{"content":"","externalUrl":null,"permalink":"/en/authors/","section":"Authors","summary":"","title":"Authors","type":"authors"},{"content":"","externalUrl":null,"permalink":"/en/series/","section":"Series","summary":"","title":"Series","type":"series"}]