diff --git a/solution/2800-2899/2823.Deep Object Filter/README_EN.md b/solution/2800-2899/2823.Deep Object Filter/README_EN.md
index 97c7c507a591f..cefde933e74fb 100644
--- a/solution/2800-2899/2823.Deep Object Filter/README_EN.md	
+++ b/solution/2800-2899/2823.Deep Object Filter/README_EN.md	
@@ -55,7 +55,7 @@ fn = (x) => Array.isArray(x)
 <ul>
 	<li><code>fn</code> is a function that returns a boolean value</li>
 	<li><code>obj</code> is a valid JSON object</li>
-	<li><code>2 &lt;= JSON.stringify(obj).length &lt;= 10**5</code></li>
+	<li><code>2 &lt;= JSON.stringify(obj).length &lt;= 10<sup>5</sup></code></li>
 </ul>
 
 ## Solutions
diff --git a/solution/2800-2899/2824.Count Pairs Whose Sum is Less than Target/README.md b/solution/2800-2899/2824.Count Pairs Whose Sum is Less than Target/README.md
new file mode 100644
index 0000000000000..ffc9ded1ca73d
--- /dev/null
+++ b/solution/2800-2899/2824.Count Pairs Whose Sum is Less than Target/README.md	
@@ -0,0 +1,175 @@
+# [2824. 统计和小于目标的下标对数目](https://leetcode.cn/problems/count-pairs-whose-sum-is-less-than-target)
+
+[English Version](/solution/2800-2899/2824.Count%20Pairs%20Whose%20Sum%20is%20Less%20than%20Target/README_EN.md)
+
+## 题目描述
+
+<!-- 这里写题目描述 -->
+
+给你一个下标从 <strong>0</strong>&nbsp;开始长度为 <code>n</code>&nbsp;的整数数组&nbsp;<code>nums</code>&nbsp;和一个整数&nbsp;<code>target</code>&nbsp;,请你返回满足&nbsp;<code>0 &lt;= i &lt; j &lt; n</code> 且 <code>nums[i] + nums[j] &lt; target</code>&nbsp;的下标对&nbsp;<code>(i, j)</code>&nbsp;的数目。
+
+<p>&nbsp;</p>
+
+<p><strong class="example">示例 1:</strong></p>
+
+<pre>
+<b>输入:</b>nums = [-1,1,2,3,1], target = 2
+<b>输出:</b>3
+<b>解释:</b>总共有 3 个下标对满足题目描述:
+- (0, 1) ,0 &lt; 1 且 nums[0] + nums[1] = 0 &lt; target
+- (0, 2) ,0 &lt; 2 且 nums[0] + nums[2] = 1 &lt; target 
+- (0, 4) ,0 &lt; 4 且 nums[0] + nums[4] = 0 &lt; target
+注意 (0, 3) 不计入答案因为 nums[0] + nums[3] 不是严格小于 target 。
+</pre>
+
+<p><strong class="example">示例 2:</strong></p>
+
+<pre>
+<b>输入:</b>nums = [-6,2,5,-2,-7,-1,3], target = -2
+<b>输出:</b>10
+<b>解释:</b>总共有 10 个下标对满足题目描述:
+- (0, 1) ,0 &lt; 1 且 nums[0] + nums[1] = -4 &lt; target
+- (0, 3) ,0 &lt; 3 且 nums[0] + nums[3] = -8 &lt; target
+- (0, 4) ,0 &lt; 4 且 nums[0] + nums[4] = -13 &lt; target
+- (0, 5) ,0 &lt; 5 且 nums[0] + nums[5] = -7 &lt; target
+- (0, 6) ,0 &lt; 6 且 nums[0] + nums[6] = -3 &lt; target
+- (1, 4) ,1 &lt; 4 且 nums[1] + nums[4] = -5 &lt; target
+- (3, 4) ,3 &lt; 4 且 nums[3] + nums[4] = -9 &lt; target
+- (3, 5) ,3 &lt; 5 且 nums[3] + nums[5] = -3 &lt; target
+- (4, 5) ,4 &lt; 5 且 nums[4] + nums[5] = -8 &lt; target
+- (4, 6) ,4 &lt; 6 且 nums[4] + nums[6] = -4 &lt; target
+</pre>
+
+<p>&nbsp;</p>
+
+<p><strong>提示:</strong></p>
+
+<ul>
+	<li><code>1 &lt;= nums.length == n &lt;= 50</code></li>
+	<li><code>-50 &lt;= nums[i], target &lt;= 50</code></li>
+</ul>
+
+## 解法
+
+<!-- 这里可写通用的实现逻辑 -->
+
+**方法一:排序 + 二分查找**
+
+我们先对数组 $nums$ 进行排序,然后枚举 $j$,在 $[0, j)$ 的范围内使用二分查找第一个大于等于 $target - nums[j]$ 的下标 $i$,那么 $[0, i)$ 的范围内的所有下标 $k$ 都满足条件,因此答案增加 $i$。
+
+遍历结束后,我们返回答案。
+
+时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 是数组 $nums$ 的长度。
+
+<!-- tabs:start -->
+
+### **Python3**
+
+<!-- 这里可写当前语言的特殊实现逻辑 -->
+
+```python
+class Solution:
+    def countPairs(self, nums: List[int], target: int) -> int:
+        nums.sort()
+        ans = 0
+        for j, x in enumerate(nums):
+            i = bisect_left(nums, target - x, hi=j)
+            ans += i
+        return ans
+```
+
+### **Java**
+
+<!-- 这里可写当前语言的特殊实现逻辑 -->
+
+```java
+class Solution {
+    public int countPairs(List<Integer> nums, int target) {
+        Collections.sort(nums);
+        int ans = 0;
+        for (int j = 0; j < nums.size(); ++j) {
+            int x = nums.get(j);
+            int i = search(nums, target - x, j);
+            ans += i;
+        }
+        return ans;
+    }
+
+    private int search(List<Integer> nums, int x, int r) {
+        int l = 0;
+        while (l < r) {
+            int mid = (l + r) >> 1;
+            if (nums.get(mid) >= x) {
+                r = mid;
+            } else {
+                l = mid + 1;
+            }
+        }
+        return l;
+    }
+}
+```
+
+### **C++**
+
+```cpp
+class Solution {
+public:
+    int countPairs(vector<int>& nums, int target) {
+        sort(nums.begin(), nums.end());
+        int ans = 0;
+        for (int j = 0; j < nums.size(); ++j) {
+            int i = lower_bound(nums.begin(), nums.begin() + j, target - nums[j]) - nums.begin();
+            ans += i;
+        }
+        return ans;
+    }
+};
+```
+
+### **Go**
+
+```go
+func countPairs(nums []int, target int) (ans int) {
+	sort.Ints(nums)
+	for j, x := range nums {
+		i := sort.SearchInts(nums[:j], target-x)
+		ans += i
+	}
+	return
+}
+```
+
+### **TypeScript**
+
+```ts
+function countPairs(nums: number[], target: number): number {
+    nums.sort((a, b) => a - b);
+    let ans = 0;
+    const search = (x: number, r: number): number => {
+        let l = 0;
+        while (l < r) {
+            const mid = (l + r) >> 1;
+            if (nums[mid] >= x) {
+                r = mid;
+            } else {
+                l = mid + 1;
+            }
+        }
+        return l;
+    };
+    for (let j = 0; j < nums.length; ++j) {
+        const i = search(target - nums[j], j);
+        ans += i;
+    }
+    return ans;
+}
+```
+
+### **...**
+
+```
+
+```
+
+<!-- tabs:end -->
diff --git a/solution/2800-2899/2824.Count Pairs Whose Sum is Less than Target/README_EN.md b/solution/2800-2899/2824.Count Pairs Whose Sum is Less than Target/README_EN.md
new file mode 100644
index 0000000000000..1c3d3d9d905f5
--- /dev/null
+++ b/solution/2800-2899/2824.Count Pairs Whose Sum is Less than Target/README_EN.md	
@@ -0,0 +1,157 @@
+# [2824. Count Pairs Whose Sum is Less than Target](https://leetcode.com/problems/count-pairs-whose-sum-is-less-than-target)
+
+[中文文档](/solution/2800-2899/2824.Count%20Pairs%20Whose%20Sum%20is%20Less%20than%20Target/README.md)
+
+## Description
+
+Given a <strong>0-indexed</strong> integer array <code>nums</code> of length <code>n</code> and an integer <code>target</code>, return <em>the number of pairs</em> <code>(i, j)</code> <em>where</em> <code>0 &lt;= i &lt; j &lt; n</code> <em>and</em> <code>nums[i] + nums[j] &lt; target</code>.
+
+<p>&nbsp;</p>
+<p><strong class="example">Example 1:</strong></p>
+
+<pre>
+<strong>Input:</strong> nums = [-1,1,2,3,1], target = 2
+<strong>Output:</strong> 3
+<strong>Explanation:</strong> There are 3 pairs of indices that satisfy the conditions in the statement:
+- (0, 1) since 0 &lt; 1 and nums[0] + nums[1] = 0 &lt; target
+- (0, 2) since 0 &lt; 2 and nums[0] + nums[2] = 1 &lt; target 
+- (0, 4) since 0 &lt; 4 and nums[0] + nums[4] = 0 &lt; target
+Note that (0, 3) is not counted since nums[0] + nums[3] is not strictly less than the target.
+</pre>
+
+<p><strong class="example">Example 2:</strong></p>
+
+<pre>
+<strong>Input:</strong> nums = [-6,2,5,-2,-7,-1,3], target = -2
+<strong>Output:</strong> 10
+<strong>Explanation:</strong> There are 10 pairs of indices that satisfy the conditions in the statement:
+- (0, 1) since 0 &lt; 1 and nums[0] + nums[1] = -4 &lt; target
+- (0, 3) since 0 &lt; 3 and nums[0] + nums[3] = -8 &lt; target
+- (0, 4) since 0 &lt; 4 and nums[0] + nums[4] = -13 &lt; target
+- (0, 5) since 0 &lt; 5 and nums[0] + nums[5] = -7 &lt; target
+- (0, 6) since 0 &lt; 6 and nums[0] + nums[6] = -3 &lt; target
+- (1, 4) since 1 &lt; 4 and nums[1] + nums[4] = -5 &lt; target
+- (3, 4) since 3 &lt; 4 and nums[3] + nums[4] = -9 &lt; target
+- (3, 5) since 3 &lt; 5 and nums[3] + nums[5] = -3 &lt; target
+- (4, 5) since 4 &lt; 5 and nums[4] + nums[5] = -8 &lt; target
+- (4, 6) since 4 &lt; 6 and nums[4] + nums[6] = -4 &lt; target
+</pre>
+
+<p>&nbsp;</p>
+<p><strong>Constraints:</strong></p>
+
+<ul>
+	<li><code>1 &lt;= nums.length == n &lt;= 50</code></li>
+	<li><code>-50 &lt;= nums[i], target &lt;= 50</code></li>
+</ul>
+
+## Solutions
+
+<!-- tabs:start -->
+
+### **Python3**
+
+```python
+class Solution:
+    def countPairs(self, nums: List[int], target: int) -> int:
+        nums.sort()
+        ans = 0
+        for j, x in enumerate(nums):
+            i = bisect_left(nums, target - x, hi=j)
+            ans += i
+        return ans
+```
+
+### **Java**
+
+```java
+class Solution {
+    public int countPairs(List<Integer> nums, int target) {
+        Collections.sort(nums);
+        int ans = 0;
+        for (int j = 0; j < nums.size(); ++j) {
+            int x = nums.get(j);
+            int i = search(nums, target - x, j);
+            ans += i;
+        }
+        return ans;
+    }
+
+    private int search(List<Integer> nums, int x, int r) {
+        int l = 0;
+        while (l < r) {
+            int mid = (l + r) >> 1;
+            if (nums.get(mid) >= x) {
+                r = mid;
+            } else {
+                l = mid + 1;
+            }
+        }
+        return l;
+    }
+}
+```
+
+### **C++**
+
+```cpp
+class Solution {
+public:
+    int countPairs(vector<int>& nums, int target) {
+        sort(nums.begin(), nums.end());
+        int ans = 0;
+        for (int j = 0; j < nums.size(); ++j) {
+            int i = lower_bound(nums.begin(), nums.begin() + j, target - nums[j]) - nums.begin();
+            ans += i;
+        }
+        return ans;
+    }
+};
+```
+
+### **Go**
+
+```go
+func countPairs(nums []int, target int) (ans int) {
+	sort.Ints(nums)
+	for j, x := range nums {
+		i := sort.SearchInts(nums[:j], target-x)
+		ans += i
+	}
+	return
+}
+```
+
+### **TypeScript**
+
+```ts
+function countPairs(nums: number[], target: number): number {
+    nums.sort((a, b) => a - b);
+    let ans = 0;
+    const search = (x: number, r: number): number => {
+        let l = 0;
+        while (l < r) {
+            const mid = (l + r) >> 1;
+            if (nums[mid] >= x) {
+                r = mid;
+            } else {
+                l = mid + 1;
+            }
+        }
+        return l;
+    };
+    for (let j = 0; j < nums.length; ++j) {
+        const i = search(target - nums[j], j);
+        ans += i;
+    }
+    return ans;
+}
+```
+
+### **...**
+
+```
+
+```
+
+<!-- tabs:end -->
diff --git a/solution/2800-2899/2824.Count Pairs Whose Sum is Less than Target/Solution.cpp b/solution/2800-2899/2824.Count Pairs Whose Sum is Less than Target/Solution.cpp
new file mode 100644
index 0000000000000..8b5f0588f7e79
--- /dev/null
+++ b/solution/2800-2899/2824.Count Pairs Whose Sum is Less than Target/Solution.cpp	
@@ -0,0 +1,12 @@
+class Solution {
+public:
+    int countPairs(vector<int>& nums, int target) {
+        sort(nums.begin(), nums.end());
+        int ans = 0;
+        for (int j = 0; j < nums.size(); ++j) {
+            int i = lower_bound(nums.begin(), nums.begin() + j, target - nums[j]) - nums.begin();
+            ans += i;
+        }
+        return ans;
+    }
+};
\ No newline at end of file
diff --git a/solution/2800-2899/2824.Count Pairs Whose Sum is Less than Target/Solution.go b/solution/2800-2899/2824.Count Pairs Whose Sum is Less than Target/Solution.go
new file mode 100644
index 0000000000000..8b1ed608a1819
--- /dev/null
+++ b/solution/2800-2899/2824.Count Pairs Whose Sum is Less than Target/Solution.go	
@@ -0,0 +1,8 @@
+func countPairs(nums []int, target int) (ans int) {
+	sort.Ints(nums)
+	for j, x := range nums {
+		i := sort.SearchInts(nums[:j], target-x)
+		ans += i
+	}
+	return
+}
\ No newline at end of file
diff --git a/solution/2800-2899/2824.Count Pairs Whose Sum is Less than Target/Solution.java b/solution/2800-2899/2824.Count Pairs Whose Sum is Less than Target/Solution.java
new file mode 100644
index 0000000000000..4467b78eb1cf8
--- /dev/null
+++ b/solution/2800-2899/2824.Count Pairs Whose Sum is Less than Target/Solution.java	
@@ -0,0 +1,25 @@
+class Solution {
+    public int countPairs(List<Integer> nums, int target) {
+        Collections.sort(nums);
+        int ans = 0;
+        for (int j = 0; j < nums.size(); ++j) {
+            int x = nums.get(j);
+            int i = search(nums, target - x, j);
+            ans += i;
+        }
+        return ans;
+    }
+
+    private int search(List<Integer> nums, int x, int r) {
+        int l = 0;
+        while (l < r) {
+            int mid = (l + r) >> 1;
+            if (nums.get(mid) >= x) {
+                r = mid;
+            } else {
+                l = mid + 1;
+            }
+        }
+        return l;
+    }
+}
\ No newline at end of file
diff --git a/solution/2800-2899/2824.Count Pairs Whose Sum is Less than Target/Solution.py b/solution/2800-2899/2824.Count Pairs Whose Sum is Less than Target/Solution.py
new file mode 100644
index 0000000000000..c7012315078ba
--- /dev/null
+++ b/solution/2800-2899/2824.Count Pairs Whose Sum is Less than Target/Solution.py	
@@ -0,0 +1,8 @@
+class Solution:
+    def countPairs(self, nums: List[int], target: int) -> int:
+        nums.sort()
+        ans = 0
+        for j, x in enumerate(nums):
+            i = bisect_left(nums, target - x, hi=j)
+            ans += i
+        return ans
diff --git a/solution/2800-2899/2824.Count Pairs Whose Sum is Less than Target/Solution.ts b/solution/2800-2899/2824.Count Pairs Whose Sum is Less than Target/Solution.ts
new file mode 100644
index 0000000000000..fd9fce8610d44
--- /dev/null
+++ b/solution/2800-2899/2824.Count Pairs Whose Sum is Less than Target/Solution.ts	
@@ -0,0 +1,21 @@
+function countPairs(nums: number[], target: number): number {
+    nums.sort((a, b) => a - b);
+    let ans = 0;
+    const search = (x: number, r: number): number => {
+        let l = 0;
+        while (l < r) {
+            const mid = (l + r) >> 1;
+            if (nums[mid] >= x) {
+                r = mid;
+            } else {
+                l = mid + 1;
+            }
+        }
+        return l;
+    };
+    for (let j = 0; j < nums.length; ++j) {
+        const i = search(target - nums[j], j);
+        ans += i;
+    }
+    return ans;
+}
diff --git a/solution/2800-2899/2825.Make String a Subsequence Using Cyclic Increments/README.md b/solution/2800-2899/2825.Make String a Subsequence Using Cyclic Increments/README.md
new file mode 100644
index 0000000000000..331bd3c49072a
--- /dev/null
+++ b/solution/2800-2899/2825.Make String a Subsequence Using Cyclic Increments/README.md	
@@ -0,0 +1,160 @@
+# [2825. 循环增长使字符串子序列等于另一个字符串](https://leetcode.cn/problems/make-string-a-subsequence-using-cyclic-increments)
+
+[English Version](/solution/2800-2899/2825.Make%20String%20a%20Subsequence%20Using%20Cyclic%20Increments/README_EN.md)
+
+## 题目描述
+
+<!-- 这里写题目描述 -->
+
+<p>给你一个下标从 <strong>0</strong>&nbsp;开始的字符串&nbsp;<code>str1</code> 和&nbsp;<code>str2</code>&nbsp;。</p>
+
+<p>一次操作中,你选择&nbsp;<code>str1</code>&nbsp;中的若干下标。对于选中的每一个下标&nbsp;<code>i</code>&nbsp;,你将&nbsp;<code>str1[i]</code>&nbsp;<strong>循环</strong>&nbsp;递增,变成下一个字符。也就是说&nbsp;<code>'a'</code>&nbsp;变成&nbsp;<code>'b'</code>&nbsp;,<code>'b'</code> 变成&nbsp;<code>'c'</code>&nbsp;,以此类推,<code>'z'</code> 变成&nbsp;<code>'a'</code>&nbsp;。</p>
+
+<p>如果执行以上操作 <strong>至多一次</strong>&nbsp;,可以让 <code>str2</code>&nbsp;成为 <code>str1</code>&nbsp;的子序列,请你返回 <code>true</code>&nbsp;,否则返回 <code>false</code>&nbsp;。</p>
+
+<p><b>注意:</b>一个字符串的子序列指的是从原字符串中删除一些(可以一个字符也不删)字符后,剩下字符按照原本先后顺序组成的新字符串。</p>
+
+<p>&nbsp;</p>
+
+<p><strong class="example">示例 1:</strong></p>
+
+<pre>
+<b>输入:</b>str1 = "abc", str2 = "ad"
+<b>输出:</b>true
+<b>解释:</b>选择 str1 中的下标 2 。
+将 str1[2] 循环递增,得到 'd' 。
+因此,str1 变成 "abd" 且 str2 现在是一个子序列。所以返回 true 。</pre>
+
+<p><strong class="example">示例 2:</strong></p>
+
+<pre>
+<b>输入:</b>str1 = "zc", str2 = "ad"
+<b>输出:</b>true
+<b>解释:</b>选择 str1 中的下标 0 和 1 。
+将 str1[0] 循环递增得到 'a' 。
+将 str1[1] 循环递增得到 'd' 。
+因此,str1 变成 "ad" 且 str2 现在是一个子序列。所以返回 true 。</pre>
+
+<p><strong class="example">示例 3:</strong></p>
+
+<pre>
+<b>输入:</b>str1 = "ab", str2 = "d"
+<b>输出:</b>false
+<b>解释:</b>这个例子中,没法在执行一次操作的前提下,将 str2 变为 str1 的子序列。
+所以返回 false 。</pre>
+
+<p>&nbsp;</p>
+
+<p><strong>提示:</strong></p>
+
+<ul>
+	<li><code>1 &lt;= str1.length &lt;= 10<sup>5</sup></code></li>
+	<li><code>1 &lt;= str2.length &lt;= 10<sup>5</sup></code></li>
+	<li><code>str1</code>&nbsp;和&nbsp;<code>str2</code>&nbsp;只包含小写英文字母。</li>
+</ul>
+
+## 解法
+
+<!-- 这里可写通用的实现逻辑 -->
+
+**方法一:双指针**
+
+本题实际上需要我们判断一个字符串 $s$ 是否为另一个字符串 $t$ 的子序列,只不过字符之间可以不完全匹配,如果两个字符相同,或者一个字符是另一个字符的下一个字符,就可以匹配。
+
+时间复杂度 $O(m + n)$,其中 $m$ 和 $n$ 分别是字符串 $str1$ 和 $str2$ 的长度。空间复杂度 $O(1)$。
+
+<!-- tabs:start -->
+
+### **Python3**
+
+<!-- 这里可写当前语言的特殊实现逻辑 -->
+
+```python
+class Solution:
+    def canMakeSubsequence(self, str1: str, str2: str) -> bool:
+        i = 0
+        for c in str1:
+            d = "a" if c == "z" else chr(ord(c) + 1)
+            if i < len(str2) and str2[i] in (c, d):
+                i += 1
+        return i == len(str2)
+```
+
+### **Java**
+
+<!-- 这里可写当前语言的特殊实现逻辑 -->
+
+```java
+class Solution {
+    public boolean canMakeSubsequence(String str1, String str2) {
+        int i = 0, n = str2.length();
+        for (char c : str1.toCharArray()) {
+            char d = c == 'z' ? 'a' : (char) (c + 1);
+            if (i < n && (str2.charAt(i) == c || str2.charAt(i) == d)) {
+                ++i;
+            }
+        }
+        return i == n;
+    }
+}
+```
+
+### **C++**
+
+```cpp
+class Solution {
+public:
+    bool canMakeSubsequence(string str1, string str2) {
+        int i = 0, n = str2.size();
+        for (char c : str1) {
+            char d = c == 'z' ? 'a' : c + 1;
+            if (i < n && (str2[i] == c || str2[i] == d)) {
+                ++i;
+            }
+        }
+        return i == n;
+    }
+};
+```
+
+### **Go**
+
+```go
+func canMakeSubsequence(str1 string, str2 string) bool {
+	i, n := 0, len(str2)
+	for _, c := range str1 {
+		d := byte('a')
+		if c != 'z' {
+			d = byte(c + 1)
+		}
+		if i < n && (str2[i] == byte(c) || str2[i] == d) {
+			i++
+		}
+	}
+	return i == n
+}
+```
+
+### **TypeScript**
+
+```ts
+function canMakeSubsequence(str1: string, str2: string): boolean {
+    let i = 0;
+    const n = str2.length;
+    for (const c of str1) {
+        const d = c === 'z' ? 'a' : String.fromCharCode(c.charCodeAt(0) + 1);
+        if (i < n && (str2[i] === c || str2[i] === d)) {
+            ++i;
+        }
+    }
+    return i === n;
+}
+```
+
+### **...**
+
+```
+
+```
+
+<!-- tabs:end -->
diff --git a/solution/2800-2899/2825.Make String a Subsequence Using Cyclic Increments/README_EN.md b/solution/2800-2899/2825.Make String a Subsequence Using Cyclic Increments/README_EN.md
new file mode 100644
index 0000000000000..d9c77bee14493
--- /dev/null
+++ b/solution/2800-2899/2825.Make String a Subsequence Using Cyclic Increments/README_EN.md	
@@ -0,0 +1,144 @@
+# [2825. Make String a Subsequence Using Cyclic Increments](https://leetcode.com/problems/make-string-a-subsequence-using-cyclic-increments)
+
+[中文文档](/solution/2800-2899/2825.Make%20String%20a%20Subsequence%20Using%20Cyclic%20Increments/README.md)
+
+## Description
+
+<p>You are given two <strong>0-indexed</strong> strings <code>str1</code> and <code>str2</code>.</p>
+
+<p>In an operation, you select a <strong>set</strong> of indices in <code>str1</code>, and for each index <code>i</code> in the set, increment <code>str1[i]</code> to the next character <strong>cyclically</strong>. That is <code>&#39;a&#39;</code> becomes <code>&#39;b&#39;</code>, <code>&#39;b&#39;</code> becomes <code>&#39;c&#39;</code>, and so on, and <code>&#39;z&#39;</code> becomes <code>&#39;a&#39;</code>.</p>
+
+<p>Return <code>true</code> <em>if it is possible to make </em><code>str2</code> <em>a subsequence of </em><code>str1</code> <em>by performing the operation <strong>at most once</strong></em>, <em>and</em> <code>false</code> <em>otherwise</em>.</p>
+
+<p><strong>Note:</strong> A subsequence of a string is a new string that is formed from the original string by deleting some (possibly none) of the characters without disturbing the relative positions of the remaining characters.</p>
+
+<p>&nbsp;</p>
+<p><strong class="example">Example 1:</strong></p>
+
+<pre>
+<strong>Input:</strong> str1 = &quot;abc&quot;, str2 = &quot;ad&quot;
+<strong>Output:</strong> true
+<strong>Explanation:</strong> Select index 2 in str1.
+Increment str1[2] to become &#39;d&#39;. 
+Hence, str1 becomes &quot;abd&quot; and str2 is now a subsequence. Therefore, true is returned.</pre>
+
+<p><strong class="example">Example 2:</strong></p>
+
+<pre>
+<strong>Input:</strong> str1 = &quot;zc&quot;, str2 = &quot;ad&quot;
+<strong>Output:</strong> true
+<strong>Explanation:</strong> Select indices 0 and 1 in str1. 
+Increment str1[0] to become &#39;a&#39;. 
+Increment str1[1] to become &#39;d&#39;. 
+Hence, str1 becomes &quot;ad&quot; and str2 is now a subsequence. Therefore, true is returned.</pre>
+
+<p><strong class="example">Example 3:</strong></p>
+
+<pre>
+<strong>Input:</strong> str1 = &quot;ab&quot;, str2 = &quot;d&quot;
+<strong>Output:</strong> false
+<strong>Explanation:</strong> In this example, it can be shown that it is impossible to make str2 a subsequence of str1 using the operation at most once. 
+Therefore, false is returned.</pre>
+
+<p>&nbsp;</p>
+<p><strong>Constraints:</strong></p>
+
+<ul>
+	<li><code>1 &lt;= str1.length &lt;= 10<sup>5</sup></code></li>
+	<li><code>1 &lt;= str2.length &lt;= 10<sup>5</sup></code></li>
+	<li><code>str1</code> and <code>str2</code> consist of only lowercase English letters.</li>
+</ul>
+
+## Solutions
+
+<!-- tabs:start -->
+
+### **Python3**
+
+```python
+class Solution:
+    def canMakeSubsequence(self, str1: str, str2: str) -> bool:
+        i = 0
+        for c in str1:
+            d = "a" if c == "z" else chr(ord(c) + 1)
+            if i < len(str2) and str2[i] in (c, d):
+                i += 1
+        return i == len(str2)
+```
+
+### **Java**
+
+```java
+class Solution {
+    public boolean canMakeSubsequence(String str1, String str2) {
+        int i = 0, n = str2.length();
+        for (char c : str1.toCharArray()) {
+            char d = c == 'z' ? 'a' : (char) (c + 1);
+            if (i < n && (str2.charAt(i) == c || str2.charAt(i) == d)) {
+                ++i;
+            }
+        }
+        return i == n;
+    }
+}
+```
+
+### **C++**
+
+```cpp
+class Solution {
+public:
+    bool canMakeSubsequence(string str1, string str2) {
+        int i = 0, n = str2.size();
+        for (char c : str1) {
+            char d = c == 'z' ? 'a' : c + 1;
+            if (i < n && (str2[i] == c || str2[i] == d)) {
+                ++i;
+            }
+        }
+        return i == n;
+    }
+};
+```
+
+### **Go**
+
+```go
+func canMakeSubsequence(str1 string, str2 string) bool {
+	i, n := 0, len(str2)
+	for _, c := range str1 {
+		d := byte('a')
+		if c != 'z' {
+			d = byte(c + 1)
+		}
+		if i < n && (str2[i] == byte(c) || str2[i] == d) {
+			i++
+		}
+	}
+	return i == n
+}
+```
+
+### **TypeScript**
+
+```ts
+function canMakeSubsequence(str1: string, str2: string): boolean {
+    let i = 0;
+    const n = str2.length;
+    for (const c of str1) {
+        const d = c === 'z' ? 'a' : String.fromCharCode(c.charCodeAt(0) + 1);
+        if (i < n && (str2[i] === c || str2[i] === d)) {
+            ++i;
+        }
+    }
+    return i === n;
+}
+```
+
+### **...**
+
+```
+
+```
+
+<!-- tabs:end -->
diff --git a/solution/2800-2899/2825.Make String a Subsequence Using Cyclic Increments/Solution.cpp b/solution/2800-2899/2825.Make String a Subsequence Using Cyclic Increments/Solution.cpp
new file mode 100644
index 0000000000000..0f3aef1f8ab9b
--- /dev/null
+++ b/solution/2800-2899/2825.Make String a Subsequence Using Cyclic Increments/Solution.cpp	
@@ -0,0 +1,13 @@
+class Solution {
+public:
+    bool canMakeSubsequence(string str1, string str2) {
+        int i = 0, n = str2.size();
+        for (char c : str1) {
+            char d = c == 'z' ? 'a' : c + 1;
+            if (i < n && (str2[i] == c || str2[i] == d)) {
+                ++i;
+            }
+        }
+        return i == n;
+    }
+};
\ No newline at end of file
diff --git a/solution/2800-2899/2825.Make String a Subsequence Using Cyclic Increments/Solution.go b/solution/2800-2899/2825.Make String a Subsequence Using Cyclic Increments/Solution.go
new file mode 100644
index 0000000000000..cf4854d6df804
--- /dev/null
+++ b/solution/2800-2899/2825.Make String a Subsequence Using Cyclic Increments/Solution.go	
@@ -0,0 +1,13 @@
+func canMakeSubsequence(str1 string, str2 string) bool {
+	i, n := 0, len(str2)
+	for _, c := range str1 {
+		d := byte('a')
+		if c != 'z' {
+			d = byte(c + 1)
+		}
+		if i < n && (str2[i] == byte(c) || str2[i] == d) {
+			i++
+		}
+	}
+	return i == n
+}
\ No newline at end of file
diff --git a/solution/2800-2899/2825.Make String a Subsequence Using Cyclic Increments/Solution.java b/solution/2800-2899/2825.Make String a Subsequence Using Cyclic Increments/Solution.java
new file mode 100644
index 0000000000000..9adce00bea6c1
--- /dev/null
+++ b/solution/2800-2899/2825.Make String a Subsequence Using Cyclic Increments/Solution.java	
@@ -0,0 +1,12 @@
+class Solution {
+    public boolean canMakeSubsequence(String str1, String str2) {
+        int i = 0, n = str2.length();
+        for (char c : str1.toCharArray()) {
+            char d = c == 'z' ? 'a' : (char) (c + 1);
+            if (i < n && (str2.charAt(i) == c || str2.charAt(i) == d)) {
+                ++i;
+            }
+        }
+        return i == n;
+    }
+}
\ No newline at end of file
diff --git a/solution/2800-2899/2825.Make String a Subsequence Using Cyclic Increments/Solution.py b/solution/2800-2899/2825.Make String a Subsequence Using Cyclic Increments/Solution.py
new file mode 100644
index 0000000000000..d47922c516f73
--- /dev/null
+++ b/solution/2800-2899/2825.Make String a Subsequence Using Cyclic Increments/Solution.py	
@@ -0,0 +1,8 @@
+class Solution:
+    def canMakeSubsequence(self, str1: str, str2: str) -> bool:
+        i = 0
+        for c in str1:
+            d = "a" if c == "z" else chr(ord(c) + 1)
+            if i < len(str2) and str2[i] in (c, d):
+                i += 1
+        return i == len(str2)
diff --git a/solution/2800-2899/2825.Make String a Subsequence Using Cyclic Increments/Solution.ts b/solution/2800-2899/2825.Make String a Subsequence Using Cyclic Increments/Solution.ts
new file mode 100644
index 0000000000000..9efebbaf5203b
--- /dev/null
+++ b/solution/2800-2899/2825.Make String a Subsequence Using Cyclic Increments/Solution.ts	
@@ -0,0 +1,11 @@
+function canMakeSubsequence(str1: string, str2: string): boolean {
+    let i = 0;
+    const n = str2.length;
+    for (const c of str1) {
+        const d = c === 'z' ? 'a' : String.fromCharCode(c.charCodeAt(0) + 1);
+        if (i < n && (str2[i] === c || str2[i] === d)) {
+            ++i;
+        }
+    }
+    return i === n;
+}
diff --git a/solution/2800-2899/2826.Sorting Three Groups/README.md b/solution/2800-2899/2826.Sorting Three Groups/README.md
new file mode 100644
index 0000000000000..e99c4cefc2d27
--- /dev/null
+++ b/solution/2800-2899/2826.Sorting Three Groups/README.md	
@@ -0,0 +1,261 @@
+# [2826. 将三个组排序](https://leetcode.cn/problems/sorting-three-groups)
+
+[English Version](/solution/2800-2899/2826.Sorting%20Three%20Groups/README_EN.md)
+
+## 题目描述
+
+<!-- 这里写题目描述 -->
+
+<p>给你一个下标从 <strong>0</strong>&nbsp;开始长度为 <code>n</code>&nbsp;的整数数组&nbsp;<code>nums</code>&nbsp;。<br />
+<br />
+从&nbsp;<code>0</code>&nbsp;到&nbsp;<code>n - 1</code>&nbsp;的数字被分为编号从&nbsp;<code>1</code>&nbsp;到&nbsp;<code>3</code>&nbsp;的三个组,数字&nbsp;<code>i</code>&nbsp;属于组&nbsp;<code>nums[i]</code>&nbsp;。注意,有的组可能是&nbsp;<strong>空的</strong>&nbsp;。<br />
+<br />
+你可以执行以下操作任意次:</p>
+
+<ul>
+	<li>选择数字&nbsp;<code>x</code>&nbsp;并改变它的组。更正式的,你可以将&nbsp;<code>nums[x]</code>&nbsp;改为数字&nbsp;<code>1</code>&nbsp;到&nbsp;<code>3</code>&nbsp;中的任意一个。</li>
+</ul>
+
+<p>你将按照以下过程构建一个新的数组&nbsp;<code>res</code>&nbsp;:</p>
+
+<ol>
+	<li>将每个组中的数字分别排序。</li>
+	<li>将组&nbsp;<code>1</code>&nbsp;,<code>2</code>&nbsp;和&nbsp;<code>3</code>&nbsp;中的元素&nbsp;<strong>依次</strong>&nbsp;连接以得到&nbsp;<code>res</code>&nbsp;。</li>
+</ol>
+
+<p>如果得到的&nbsp;<code>res</code>&nbsp;是 <strong>非递减</strong>顺序的,那么我们称数组&nbsp;<code>nums</code>&nbsp;是 <strong>美丽数组</strong>&nbsp;。</p>
+
+<p>请你返回将<em>&nbsp;</em><code>nums</code>&nbsp;变为&nbsp;<strong>美丽数组</strong>&nbsp;需要的最少步数。</p>
+
+<p>&nbsp;</p>
+
+<p><strong class="example">示例 1:</strong></p>
+
+<pre>
+<b>输入:</b>nums = [2,1,3,2,1]
+<b>输出:</b>3
+<b>解释:</b>以下三步操作是最优方案:
+1. 将 nums[0] 变为 1 。
+2. 将 nums[2] 变为 1 。
+3. 将 nums[3] 变为 1 。
+执行以上操作后,将每组中的数字排序,组 1 为 [0,1,2,3,4] ,组 2 和组 3 都为空。所以 res 等于 [0,1,2,3,4] ,它是非递减顺序的。
+三步操作是最少需要的步数。
+</pre>
+
+<p><strong class="example">示例 2:</strong></p>
+
+<pre>
+<b>输入:</b>nums = [1,3,2,1,3,3]
+<b>输出:</b>2
+<b>解释:</b>以下两步操作是最优方案:
+1. 将 nums[1] 变为 1 。
+2. 将 nums[2] 变为 1 。
+执行以上操作后,将每组中的数字排序,组 1 为 [0,1,2,3] ,组 2 为空,组 3 为 [4,5] 。所以 res 等于 [0,1,2,3,4,5] ,它是非递减顺序的。
+两步操作是最少需要的步数。
+</pre>
+
+<p><strong class="example">示例 3:</strong></p>
+
+<pre>
+<b>输入:</b>nums = [2,2,2,2,3,3]
+<b>输出:</b>0
+<b>解释:</b>不需要执行任何操作。
+组 1 为空,组 2 为 [0,1,2,3] ,组 3 为 [4,5] 。所以 res 等于 [0,1,2,3,4,5] ,它是非递减顺序的。
+</pre>
+
+<p>&nbsp;</p>
+
+<p><strong>提示:</strong></p>
+
+<ul>
+	<li><code>1 &lt;= nums.length &lt;= 100</code></li>
+	<li><code>1 &lt;= nums[i] &lt;= 3</code></li>
+</ul>
+
+## 解法
+
+<!-- 这里可写通用的实现逻辑 -->
+
+**方法一:动态规划**
+
+我们定义 $f[i][j]$ 表示将前 $i$ 个数变成美丽数组,并且第 $i$ 个数变成 $j+1$ 的最少操作次数。那么答案就是 $min(f[n][0], f[n][1], f[n][2])$。
+
+我们可以枚举第 $i$ 个数变成 $j+1$ 的所有情况,然后取最小值。这里我们可以用滚动数组优化空间复杂度。
+
+时间复杂度 $O(n)$,其中 $n$ 是数组的长度。空间复杂度 $O(1)$。
+
+<!-- tabs:start -->
+
+### **Python3**
+
+<!-- 这里可写当前语言的特殊实现逻辑 -->
+
+```python
+class Solution:
+    def minimumOperations(self, nums: List[int]) -> int:
+        f = g = h = 0
+        for x in nums:
+            ff = gg = hh = 0
+            if x == 1:
+                ff = f
+                gg = min(f, g) + 1
+                hh = min(f, g, h) + 1
+            elif x == 2:
+                ff = f + 1
+                gg = min(f, g)
+                hh = min(f, g, h) + 1
+            else:
+                ff = f + 1
+                gg = min(f, g) + 1
+                hh = min(f, g, h)
+            f, g, h = ff, gg, hh
+        return min(f, g, h)
+```
+
+```python
+class Solution:
+    def minimumOperations(self, nums: List[int]) -> int:
+        f = [0] * 3
+        for x in nums:
+            g = [0] * 3
+            if x == 1:
+                g[0] = f[0]
+                g[1] = min(f[:2]) + 1
+                g[2] = min(f) + 1
+            elif x == 2:
+                g[0] = f[0] + 1
+                g[1] = min(f[:2])
+                g[2] = min(f) + 1
+            else:
+                g[0] = f[0] + 1
+                g[1] = min(f[:2]) + 1
+                g[2] = min(f)
+            f = g
+        return min(f)
+```
+
+### **Java**
+
+<!-- 这里可写当前语言的特殊实现逻辑 -->
+
+```java
+class Solution {
+    public int minimumOperations(List<Integer> nums) {
+        int[] f = new int[3];
+        for (int x : nums) {
+            int[] g = new int[3];
+            if (x == 1) {
+                g[0] = f[0];
+                g[1] = Math.min(f[0], f[1]) + 1;
+                g[2] = Math.min(f[0], Math.min(f[1], f[2])) + 1;
+            } else if (x == 2) {
+                g[0] = f[0] + 1;
+                g[1] = Math.min(f[0], f[1]);
+                g[2] = Math.min(f[0], Math.min(f[1], f[2])) + 1;
+            } else {
+                g[0] = f[0] + 1;
+                g[1] = Math.min(f[0], f[1]) + 1;
+                g[2] = Math.min(f[0], Math.min(f[1], f[2]));
+            }
+            f = g;
+        }
+        return Math.min(f[0], Math.min(f[1], f[2]));
+    }
+}
+```
+
+### **C++**
+
+```cpp
+class Solution {
+public:
+    int minimumOperations(vector<int>& nums) {
+        vector<int> f(3);
+        for (int x : nums) {
+            vector<int> g(3);
+            if (x == 1) {
+                g[0] = f[0];
+                g[1] = min(f[0], f[1]) + 1;
+                g[2] = min({f[0], f[1], f[2]}) + 1;
+            } else if (x == 2) {
+                g[0] = f[0] + 1;
+                g[1] = min(f[0], f[1]);
+                g[2] = min(f[0], min(f[1], f[2])) + 1;
+            } else {
+                g[0] = f[0] + 1;
+                g[1] = min(f[0], f[1]) + 1;
+                g[2] = min(f[0], min(f[1], f[2]));
+            }
+            f = move(g);
+        }
+        return min({f[0], f[1], f[2]});
+    }
+};
+```
+
+### **Go**
+
+```go
+func minimumOperations(nums []int) int {
+	f := make([]int, 3)
+	for _, x := range nums {
+		g := make([]int, 3)
+		if x == 1 {
+			g[0] = f[0]
+			g[1] = min(f[0], f[1]) + 1
+			g[2] = min(f[0], min(f[1], f[2])) + 1
+		} else if x == 2 {
+			g[0] = f[0] + 1
+			g[1] = min(f[0], f[1])
+			g[2] = min(f[0], min(f[1], f[2])) + 1
+		} else {
+			g[0] = f[0] + 1
+			g[1] = min(f[0], f[1]) + 1
+			g[2] = min(f[0], min(f[1], f[2]))
+		}
+		f = g
+	}
+	return min(f[0], min(f[1], f[2]))
+}
+
+func min(a, b int) int {
+	if a < b {
+		return a
+	}
+	return b
+}
+```
+
+### **TypeScript**
+
+```ts
+function minimumOperations(nums: number[]): number {
+    let f: number[] = new Array(3).fill(0);
+    for (const x of nums) {
+        const g: number[] = new Array(3).fill(0);
+        if (x === 1) {
+            g[0] = f[0];
+            g[1] = Math.min(f[0], f[1]) + 1;
+            g[2] = Math.min(f[0], Math.min(f[1], f[2])) + 1;
+        } else if (x === 2) {
+            g[0] = f[0] + 1;
+            g[1] = Math.min(f[0], f[1]);
+            g[2] = Math.min(f[0], Math.min(f[1], f[2])) + 1;
+        } else {
+            g[0] = f[0] + 1;
+            g[1] = Math.min(f[0], f[1]) + 1;
+            g[2] = Math.min(f[0], Math.min(f[1], f[2]));
+        }
+        f = g;
+    }
+    return Math.min(...f);
+}
+```
+
+### **...**
+
+```
+
+```
+
+<!-- tabs:end -->
diff --git a/solution/2800-2899/2826.Sorting Three Groups/README_EN.md b/solution/2800-2899/2826.Sorting Three Groups/README_EN.md
new file mode 100644
index 0000000000000..a089b38e21bc6
--- /dev/null
+++ b/solution/2800-2899/2826.Sorting Three Groups/README_EN.md	
@@ -0,0 +1,243 @@
+# [2826. Sorting Three Groups](https://leetcode.com/problems/sorting-three-groups)
+
+[中文文档](/solution/2800-2899/2826.Sorting%20Three%20Groups/README.md)
+
+## Description
+
+<p>You are given a <strong>0-indexed</strong> integer array <code>nums</code> of length <code>n</code>.<br />
+<br />
+The numbers from <code>0</code> to <code>n - 1</code> are divided into three groups numbered from <code>1</code> to <code>3</code>, where number <code>i</code> belongs to group <code>nums[i]</code>. Notice that some groups may be <strong>empty</strong>.<br />
+<br />
+You are allowed to perform this operation any number of times:</p>
+
+<ul>
+	<li>Pick number <code>x</code> and change its group. More formally, change <code>nums[x]</code> to any number from <code>1</code> to <code>3</code>.</li>
+</ul>
+
+<p>A new array <code>res</code> is constructed using the following procedure:</p>
+
+<ol>
+	<li>Sort the numbers in each group independently.</li>
+	<li>Append the elements of groups <code>1</code>, <code>2</code>, and <code>3</code> to <code>res</code> <strong>in this order</strong>.</li>
+</ol>
+
+<p>Array <code>nums</code> is called a <strong>beautiful array</strong> if the constructed array <code>res</code> is sorted in <strong>non-decreasing</strong> order.</p>
+
+<p>Return <em>the <strong>minimum</strong> number of operations to make </em><code>nums</code><em> a <strong>beautiful array</strong></em>.</p>
+
+<p>&nbsp;</p>
+<p><strong class="example">Example 1:</strong></p>
+
+<pre>
+<strong>Input:</strong> nums = [2,1,3,2,1]
+<strong>Output:</strong> 3
+<strong>Explanation:</strong> It&#39;s optimal to perform three operations:
+1. change nums[0] to 1.
+2. change nums[2] to 1.
+3. change nums[3] to 1.
+After performing the operations and sorting the numbers in each group, group 1 becomes equal to [0,1,2,3,4] and group 2 and group 3 become empty. Hence, res is equal to [0,1,2,3,4] which is sorted in non-decreasing order.
+It can be proven that there is no valid sequence of less than three operations.
+</pre>
+
+<p><strong class="example">Example 2:</strong></p>
+
+<pre>
+<strong>Input:</strong> nums = [1,3,2,1,3,3]
+<strong>Output:</strong> 2
+<strong>Explanation:</strong> It&#39;s optimal to perform two operations:
+1. change nums[1] to 1.
+2. change nums[2] to 1.
+After performing the operations and sorting the numbers in each group, group 1 becomes equal to [0,1,2,3], group 2 becomes empty, and group 3 becomes equal to [4,5]. Hence, res is equal to [0,1,2,3,4,5] which is sorted in non-decreasing order.
+It can be proven that there is no valid sequence of less than two operations.
+</pre>
+
+<p><strong class="example">Example 3:</strong></p>
+
+<pre>
+<strong>Input:</strong> nums = [2,2,2,2,3,3]
+<strong>Output:</strong> 0
+<strong>Explanation:</strong> It&#39;s optimal to not perform operations.
+After sorting the numbers in each group, group 1 becomes empty, group 2 becomes equal to [0,1,2,3] and group 3 becomes equal to [4,5]. Hence, res is equal to [0,1,2,3,4,5] which is sorted in non-decreasing order.
+</pre>
+
+<p>&nbsp;</p>
+<p><strong>Constraints:</strong></p>
+
+<ul>
+	<li><code>1 &lt;= nums.length &lt;= 100</code></li>
+	<li><code>1 &lt;= nums[i] &lt;= 3</code></li>
+</ul>
+
+## Solutions
+
+<!-- tabs:start -->
+
+### **Python3**
+
+```python
+class Solution:
+    def minimumOperations(self, nums: List[int]) -> int:
+        f = g = h = 0
+        for x in nums:
+            ff = gg = hh = 0
+            if x == 1:
+                ff = f
+                gg = min(f, g) + 1
+                hh = min(f, g, h) + 1
+            elif x == 2:
+                ff = f + 1
+                gg = min(f, g)
+                hh = min(f, g, h) + 1
+            else:
+                ff = f + 1
+                gg = min(f, g) + 1
+                hh = min(f, g, h)
+            f, g, h = ff, gg, hh
+        return min(f, g, h)
+```
+
+```python
+class Solution:
+    def minimumOperations(self, nums: List[int]) -> int:
+        f = [0] * 3
+        for x in nums:
+            g = [0] * 3
+            if x == 1:
+                g[0] = f[0]
+                g[1] = min(f[:2]) + 1
+                g[2] = min(f) + 1
+            elif x == 2:
+                g[0] = f[0] + 1
+                g[1] = min(f[:2])
+                g[2] = min(f) + 1
+            else:
+                g[0] = f[0] + 1
+                g[1] = min(f[:2]) + 1
+                g[2] = min(f)
+            f = g
+        return min(f)
+```
+
+### **Java**
+
+```java
+class Solution {
+    public int minimumOperations(List<Integer> nums) {
+        int[] f = new int[3];
+        for (int x : nums) {
+            int[] g = new int[3];
+            if (x == 1) {
+                g[0] = f[0];
+                g[1] = Math.min(f[0], f[1]) + 1;
+                g[2] = Math.min(f[0], Math.min(f[1], f[2])) + 1;
+            } else if (x == 2) {
+                g[0] = f[0] + 1;
+                g[1] = Math.min(f[0], f[1]);
+                g[2] = Math.min(f[0], Math.min(f[1], f[2])) + 1;
+            } else {
+                g[0] = f[0] + 1;
+                g[1] = Math.min(f[0], f[1]) + 1;
+                g[2] = Math.min(f[0], Math.min(f[1], f[2]));
+            }
+            f = g;
+        }
+        return Math.min(f[0], Math.min(f[1], f[2]));
+    }
+}
+```
+
+### **C++**
+
+```cpp
+class Solution {
+public:
+    int minimumOperations(vector<int>& nums) {
+        vector<int> f(3);
+        for (int x : nums) {
+            vector<int> g(3);
+            if (x == 1) {
+                g[0] = f[0];
+                g[1] = min(f[0], f[1]) + 1;
+                g[2] = min({f[0], f[1], f[2]}) + 1;
+            } else if (x == 2) {
+                g[0] = f[0] + 1;
+                g[1] = min(f[0], f[1]);
+                g[2] = min(f[0], min(f[1], f[2])) + 1;
+            } else {
+                g[0] = f[0] + 1;
+                g[1] = min(f[0], f[1]) + 1;
+                g[2] = min(f[0], min(f[1], f[2]));
+            }
+            f = move(g);
+        }
+        return min({f[0], f[1], f[2]});
+    }
+};
+```
+
+### **Go**
+
+```go
+func minimumOperations(nums []int) int {
+	f := make([]int, 3)
+	for _, x := range nums {
+		g := make([]int, 3)
+		if x == 1 {
+			g[0] = f[0]
+			g[1] = min(f[0], f[1]) + 1
+			g[2] = min(f[0], min(f[1], f[2])) + 1
+		} else if x == 2 {
+			g[0] = f[0] + 1
+			g[1] = min(f[0], f[1])
+			g[2] = min(f[0], min(f[1], f[2])) + 1
+		} else {
+			g[0] = f[0] + 1
+			g[1] = min(f[0], f[1]) + 1
+			g[2] = min(f[0], min(f[1], f[2]))
+		}
+		f = g
+	}
+	return min(f[0], min(f[1], f[2]))
+}
+
+func min(a, b int) int {
+	if a < b {
+		return a
+	}
+	return b
+}
+```
+
+### **TypeScript**
+
+```ts
+function minimumOperations(nums: number[]): number {
+    let f: number[] = new Array(3).fill(0);
+    for (const x of nums) {
+        const g: number[] = new Array(3).fill(0);
+        if (x === 1) {
+            g[0] = f[0];
+            g[1] = Math.min(f[0], f[1]) + 1;
+            g[2] = Math.min(f[0], Math.min(f[1], f[2])) + 1;
+        } else if (x === 2) {
+            g[0] = f[0] + 1;
+            g[1] = Math.min(f[0], f[1]);
+            g[2] = Math.min(f[0], Math.min(f[1], f[2])) + 1;
+        } else {
+            g[0] = f[0] + 1;
+            g[1] = Math.min(f[0], f[1]) + 1;
+            g[2] = Math.min(f[0], Math.min(f[1], f[2]));
+        }
+        f = g;
+    }
+    return Math.min(...f);
+}
+```
+
+### **...**
+
+```
+
+```
+
+<!-- tabs:end -->
diff --git a/solution/2800-2899/2826.Sorting Three Groups/Solution.cpp b/solution/2800-2899/2826.Sorting Three Groups/Solution.cpp
new file mode 100644
index 0000000000000..58e0b94d63e6e
--- /dev/null
+++ b/solution/2800-2899/2826.Sorting Three Groups/Solution.cpp	
@@ -0,0 +1,24 @@
+class Solution {
+public:
+    int minimumOperations(vector<int>& nums) {
+        vector<int> f(3);
+        for (int x : nums) {
+            vector<int> g(3);
+            if (x == 1) {
+                g[0] = f[0];
+                g[1] = min(f[0], f[1]) + 1;
+                g[2] = min({f[0], f[1], f[2]}) + 1;
+            } else if (x == 2) {
+                g[0] = f[0] + 1;
+                g[1] = min(f[0], f[1]);
+                g[2] = min(f[0], min(f[1], f[2])) + 1;
+            } else {
+                g[0] = f[0] + 1;
+                g[1] = min(f[0], f[1]) + 1;
+                g[2] = min(f[0], min(f[1], f[2]));
+            }
+            f = move(g);
+        }
+        return min({f[0], f[1], f[2]});
+    }
+};
\ No newline at end of file
diff --git a/solution/2800-2899/2826.Sorting Three Groups/Solution.go b/solution/2800-2899/2826.Sorting Three Groups/Solution.go
new file mode 100644
index 0000000000000..ed0f1237c7cbb
--- /dev/null
+++ b/solution/2800-2899/2826.Sorting Three Groups/Solution.go	
@@ -0,0 +1,28 @@
+func minimumOperations(nums []int) int {
+	f := make([]int, 3)
+	for _, x := range nums {
+		g := make([]int, 3)
+		if x == 1 {
+			g[0] = f[0]
+			g[1] = min(f[0], f[1]) + 1
+			g[2] = min(f[0], min(f[1], f[2])) + 1
+		} else if x == 2 {
+			g[0] = f[0] + 1
+			g[1] = min(f[0], f[1])
+			g[2] = min(f[0], min(f[1], f[2])) + 1
+		} else {
+			g[0] = f[0] + 1
+			g[1] = min(f[0], f[1]) + 1
+			g[2] = min(f[0], min(f[1], f[2]))
+		}
+		f = g
+	}
+	return min(f[0], min(f[1], f[2]))
+}
+
+func min(a, b int) int {
+	if a < b {
+		return a
+	}
+	return b
+}
\ No newline at end of file
diff --git a/solution/2800-2899/2826.Sorting Three Groups/Solution.java b/solution/2800-2899/2826.Sorting Three Groups/Solution.java
new file mode 100644
index 0000000000000..41ed065505650
--- /dev/null
+++ b/solution/2800-2899/2826.Sorting Three Groups/Solution.java	
@@ -0,0 +1,23 @@
+class Solution {
+    public int minimumOperations(List<Integer> nums) {
+        int[] f = new int[3];
+        for (int x : nums) {
+            int[] g = new int[3];
+            if (x == 1) {
+                g[0] = f[0];
+                g[1] = Math.min(f[0], f[1]) + 1;
+                g[2] = Math.min(f[0], Math.min(f[1], f[2])) + 1;
+            } else if (x == 2) {
+                g[0] = f[0] + 1;
+                g[1] = Math.min(f[0], f[1]);
+                g[2] = Math.min(f[0], Math.min(f[1], f[2])) + 1;
+            } else {
+                g[0] = f[0] + 1;
+                g[1] = Math.min(f[0], f[1]) + 1;
+                g[2] = Math.min(f[0], Math.min(f[1], f[2]));
+            }
+            f = g;
+        }
+        return Math.min(f[0], Math.min(f[1], f[2]));
+    }
+}
\ No newline at end of file
diff --git a/solution/2800-2899/2826.Sorting Three Groups/Solution.py b/solution/2800-2899/2826.Sorting Three Groups/Solution.py
new file mode 100644
index 0000000000000..254580d561ea0
--- /dev/null
+++ b/solution/2800-2899/2826.Sorting Three Groups/Solution.py	
@@ -0,0 +1,19 @@
+class Solution:
+    def minimumOperations(self, nums: List[int]) -> int:
+        f = [0] * 3
+        for x in nums:
+            g = [0] * 3
+            if x == 1:
+                g[0] = f[0]
+                g[1] = min(f[:2]) + 1
+                g[2] = min(f) + 1
+            elif x == 2:
+                g[0] = f[0] + 1
+                g[1] = min(f[:2])
+                g[2] = min(f) + 1
+            else:
+                g[0] = f[0] + 1
+                g[1] = min(f[:2]) + 1
+                g[2] = min(f)
+            f = g
+        return min(f)
diff --git a/solution/2800-2899/2826.Sorting Three Groups/Solution.ts b/solution/2800-2899/2826.Sorting Three Groups/Solution.ts
new file mode 100644
index 0000000000000..00e8cc4ca8632
--- /dev/null
+++ b/solution/2800-2899/2826.Sorting Three Groups/Solution.ts	
@@ -0,0 +1,21 @@
+function minimumOperations(nums: number[]): number {
+    let f: number[] = new Array(3).fill(0);
+    for (const x of nums) {
+        const g: number[] = new Array(3).fill(0);
+        if (x === 1) {
+            g[0] = f[0];
+            g[1] = Math.min(f[0], f[1]) + 1;
+            g[2] = Math.min(f[0], Math.min(f[1], f[2])) + 1;
+        } else if (x === 2) {
+            g[0] = f[0] + 1;
+            g[1] = Math.min(f[0], f[1]);
+            g[2] = Math.min(f[0], Math.min(f[1], f[2])) + 1;
+        } else {
+            g[0] = f[0] + 1;
+            g[1] = Math.min(f[0], f[1]) + 1;
+            g[2] = Math.min(f[0], Math.min(f[1], f[2]));
+        }
+        f = g;
+    }
+    return Math.min(...f);
+}
diff --git a/solution/2800-2899/2827.Number of Beautiful Integers in the Range/README.md b/solution/2800-2899/2827.Number of Beautiful Integers in the Range/README.md
new file mode 100644
index 0000000000000..48271e9bbfa8a
--- /dev/null
+++ b/solution/2800-2899/2827.Number of Beautiful Integers in the Range/README.md	
@@ -0,0 +1,343 @@
+# [2827. 范围中美丽整数的数目](https://leetcode.cn/problems/number-of-beautiful-integers-in-the-range)
+
+[English Version](/solution/2800-2899/2827.Number%20of%20Beautiful%20Integers%20in%20the%20Range/README_EN.md)
+
+## 题目描述
+
+<!-- 这里写题目描述 -->
+
+<p>给你正整数&nbsp;<code>low</code>&nbsp;,<code>high</code>&nbsp;和&nbsp;<code>k</code>&nbsp;。</p>
+
+<p>如果一个数满足以下两个条件,那么它是 <strong>美丽的</strong>&nbsp;:</p>
+
+<ul>
+	<li>偶数数位的数目与奇数数位的数目相同。</li>
+	<li>这个整数可以被&nbsp;<code>k</code>&nbsp;整除。</li>
+</ul>
+
+<p>请你返回范围&nbsp;<code>[low, high]</code>&nbsp;中美丽整数的数目。</p>
+
+<p>&nbsp;</p>
+
+<p><strong class="example">示例 1:</strong></p>
+
+<pre>
+<b>输入:</b>low = 10, high = 20, k = 3
+<b>输出:</b>2
+<b>解释:</b>给定范围中有 2 个美丽数字:[12,18]
+- 12 是美丽整数,因为它有 1 个奇数数位和 1 个偶数数位,而且可以被 k = 3 整除。
+- 18 是美丽整数,因为它有 1 个奇数数位和 1 个偶数数位,而且可以被 k = 3 整除。
+以下是一些不是美丽整数的例子:
+- 16 不是美丽整数,因为它不能被 k = 3 整除。
+- 15 不是美丽整数,因为它的奇数数位和偶数数位的数目不相等。
+给定范围内总共有 2 个美丽整数。
+</pre>
+
+<p><strong class="example">示例 2:</strong></p>
+
+<pre>
+<b>输入:</b>low = 1, high = 10, k = 1
+<b>输出:</b>1
+<b>解释:</b>给定范围中有 1 个美丽数字:[10]
+- 10 是美丽整数,因为它有 1 个奇数数位和 1 个偶数数位,而且可以被 k = 1 整除。
+给定范围内总共有 1 个美丽整数。
+</pre>
+
+<p><strong class="example">示例 3:</strong></p>
+
+<pre>
+<b>输入:</b>low = 5, high = 5, k = 2
+<b>输出:</b>0
+<b>解释:</b>给定范围中有 0 个美丽数字。
+- 5 不是美丽整数,因为它的奇数数位和偶数数位的数目不相等。
+</pre>
+
+<p>&nbsp;</p>
+
+<p><strong>提示:</strong></p>
+
+<ul>
+	<li><code>0 &lt; low &lt;= high &lt;= 10<sup>9</sup></code></li>
+	<li><code>0 &lt; k &lt;= 20</code></li>
+</ul>
+
+## 解法
+
+<!-- 这里可写通用的实现逻辑 -->
+
+**方法一:数位 DP**
+
+我们注意到,题目求的是区间 $[low, high]$ 内的步进数的个数,对于这种区间 $[l,..r]$ 的问题,我们通常可以考虑转化为求 $[1, r]$ 和 $[1, l-1]$ 的答案,然后相减即可。另外,题目中只涉及到不同数位之间的关系,而不涉及具体的数值,因此我们可以考虑使用数位 DP 来解决。
+
+我们设计一个函数 $dfs(pos, mod, diff, lead, limit)$,表示当前处理到第 $pos$ 位,当前数字模 $k$ 的结果为 $mod$,当前数字的奇偶数位差为 $diff$,当前数字是否有前导零为 $lead$,当前数字是否达到上界为 $limit$ 时的方案数。
+
+函数 $dfs(pos, mod, diff, lead, limit)$ 的执行逻辑如下:
+
+如果 $pos$ 超出了 $num$ 的长度,说明我们已经处理完了所有数位,如果此时 $mod=0$,并且 $diff=0$,说明当前数字满足题目要求,我们返回 $1$,否则返回 $0$。
+
+否则,我们计算得到当前数位的上界 $up$,然后在 $[0,..up]$ 范围内枚举当前数位的数字 $i$:
+
+-   如果 $i=0$ 且 $lead$ 为真,说明当前数字只包含前导零,我们递归计算 $dfs(pos + 1, mod, diff, 1, limit\ and\ i=up)$ 的值并累加到答案中;
+-   否则,我们根据 $i$ 的奇偶性更新 $diff$ 的值,然后递归计算 $dfs(pos + 1, (mod \times 10 + i) \bmod k, diff, 0, limit\ and\ i=up)$ 的值并累加到答案中。
+
+最终我们返回答案。
+
+在主函数中,我们分别计算 $[1, high]$ 和 $[1, low-1]$ 的答案 $a$ 和 $b$,最终答案为 $a-b$。
+
+时间复杂度 $O((\log M)^2 \times k \times |\Sigma|)$,空间复杂度 $O((\log M)^2 \times k \times)$,其中 $M$ 表示 $high$ 数字的大小,而 $|\Sigma|$ 表示数字集合。
+
+相似题目:
+
+-   [2719. 统计整数数目](/solution/2700-2799/2719.Count%20of%20Integers/README.md)
+
+<!-- tabs:start -->
+
+### **Python3**
+
+<!-- 这里可写当前语言的特殊实现逻辑 -->
+
+```python
+class Solution:
+    def numberOfBeautifulIntegers(self, low: int, high: int, k: int) -> int:
+        @cache
+        def dfs(pos: int, mod: int, diff: int, lead: int, limit: int) -> int:
+            if pos >= len(s):
+                return mod == 0 and diff == 10
+            up = int(s[pos]) if limit else 9
+            ans = 0
+            for i in range(up + 1):
+                if i == 0 and lead:
+                    ans += dfs(pos + 1, mod, diff, 1, limit and i == up)
+                else:
+                    nxt = diff + (1 if i % 2 == 1 else -1)
+                    ans += dfs(pos + 1, (mod * 10 + i) % k, nxt, 0, limit and i == up)
+            return ans
+
+        s = str(high)
+        a = dfs(0, 0, 10, 1, 1)
+        dfs.cache_clear()
+        s = str(low - 1)
+        b = dfs(0, 0, 10, 1, 1)
+        return a - b
+```
+
+### **Java**
+
+<!-- 这里可写当前语言的特殊实现逻辑 -->
+
+```java
+class Solution {
+    private String s;
+    private int k;
+    private Integer[][][] f = new Integer[11][21][21];
+
+    public int numberOfBeautifulIntegers(int low, int high, int k) {
+        this.k = k;
+        s = String.valueOf(high);
+        int a = dfs(0, 0, 10, true, true);
+        s = String.valueOf(low - 1);
+        f = new Integer[11][21][21];
+        int b = dfs(0, 0, 10, true, true);
+        return a - b;
+    }
+
+    private int dfs(int pos, int mod, int diff, boolean lead, boolean limit) {
+        if (pos >= s.length()) {
+            return mod == 0 && diff == 10 ? 1 : 0;
+        }
+        if (!lead && !limit && f[pos][mod][diff] != null) {
+            return f[pos][mod][diff];
+        }
+        int ans = 0;
+        int up = limit ? s.charAt(pos) - '0' : 9;
+        for (int i = 0; i <= up; ++i) {
+            if (i == 0 && lead) {
+                ans += dfs(pos + 1, mod, diff, true, limit && i == up);
+            } else {
+                int nxt = diff + (i % 2 == 1 ? 1 : -1);
+                ans += dfs(pos + 1, (mod * 10 + i) % k, nxt, false, limit && i == up);
+            }
+        }
+        if (!lead && !limit) {
+            f[pos][mod][diff] = ans;
+        }
+        return ans;
+    }
+}
+```
+
+### **C++**
+
+```cpp
+class Solution {
+public:
+    int numberOfBeautifulIntegers(int low, int high, int k) {
+        int f[11][21][21];
+        memset(f, -1, sizeof(f));
+        string s = to_string(high);
+
+        function<int(int, int, int, bool, bool)> dfs = [&](int pos, int mod, int diff, bool lead, bool limit) {
+            if (pos >= s.size()) {
+                return mod == 0 && diff == 10 ? 1 : 0;
+            }
+            if (!lead && !limit && f[pos][mod][diff] != -1) {
+                return f[pos][mod][diff];
+            }
+            int ans = 0;
+            int up = limit ? s[pos] - '0' : 9;
+            for (int i = 0; i <= up; ++i) {
+                if (i == 0 && lead) {
+                    ans += dfs(pos + 1, mod, diff, true, limit && i == up);
+                } else {
+                    int nxt = diff + (i % 2 == 1 ? 1 : -1);
+                    ans += dfs(pos + 1, (mod * 10 + i) % k, nxt, false, limit && i == up);
+                }
+            }
+            if (!lead && !limit) {
+                f[pos][mod][diff] = ans;
+            }
+            return ans;
+        };
+
+        int a = dfs(0, 0, 10, true, true);
+        memset(f, -1, sizeof(f));
+        s = to_string(low - 1);
+        int b = dfs(0, 0, 10, true, true);
+        return a - b;
+    }
+};
+```
+
+### **Go**
+
+```go
+func numberOfBeautifulIntegers(low int, high int, k int) int {
+	s := strconv.Itoa(high)
+	f := g(len(s), k, 21)
+
+	var dfs func(pos, mod, diff int, lead, limit bool) int
+	dfs = func(pos, mod, diff int, lead, limit bool) int {
+		if pos >= len(s) {
+			if mod == 0 && diff == 10 {
+				return 1
+			}
+			return 0
+		}
+		if !lead && !limit && f[pos][mod][diff] != -1 {
+			return f[pos][mod][diff]
+		}
+		up := 9
+		if limit {
+			up = int(s[pos] - '0')
+		}
+		ans := 0
+		for i := 0; i <= up; i++ {
+			if i == 0 && lead {
+				ans += dfs(pos+1, mod, diff, true, limit && i == up)
+			} else {
+				nxt := diff + 1
+				if i%2 == 0 {
+					nxt -= 2
+				}
+				ans += dfs(pos+1, (mod*10+i)%k, nxt, false, limit && i == up)
+			}
+		}
+		if !lead && !limit {
+			f[pos][mod][diff] = ans
+		}
+		return ans
+	}
+
+	a := dfs(0, 0, 10, true, true)
+	s = strconv.Itoa(low - 1)
+	f = g(len(s), k, 21)
+	b := dfs(0, 0, 10, true, true)
+	return a - b
+}
+
+func g(m, n, k int) [][][]int {
+	f := make([][][]int, m)
+	for i := 0; i < m; i++ {
+		f[i] = make([][]int, n)
+		for j := 0; j < n; j++ {
+			f[i][j] = make([]int, k)
+			for d := 0; d < k; d++ {
+				f[i][j][d] = -1
+			}
+		}
+	}
+	return f
+}
+```
+
+### **TypeScript**
+
+```ts
+function numberOfBeautifulIntegers(
+    low: number,
+    high: number,
+    k: number,
+): number {
+    let s = String(high);
+    let f: number[][][] = Array(11)
+        .fill(0)
+        .map(() =>
+            Array(21)
+                .fill(0)
+                .map(() => Array(21).fill(-1)),
+        );
+    const dfs = (
+        pos: number,
+        mod: number,
+        diff: number,
+        lead: boolean,
+        limit: boolean,
+    ): number => {
+        if (pos >= s.length) {
+            return mod == 0 && diff == 10 ? 1 : 0;
+        }
+        if (!lead && !limit && f[pos][mod][diff] != -1) {
+            return f[pos][mod][diff];
+        }
+        let ans = 0;
+        const up = limit ? Number(s[pos]) : 9;
+        for (let i = 0; i <= up; ++i) {
+            if (i === 0 && lead) {
+                ans += dfs(pos + 1, mod, diff, true, limit && i === up);
+            } else {
+                const nxt = diff + (i % 2 ? 1 : -1);
+                ans += dfs(
+                    pos + 1,
+                    (mod * 10 + i) % k,
+                    nxt,
+                    false,
+                    limit && i === up,
+                );
+            }
+        }
+        if (!lead && !limit) {
+            f[pos][mod][diff] = ans;
+        }
+        return ans;
+    };
+    const a = dfs(0, 0, 10, true, true);
+    s = String(low - 1);
+    f = Array(11)
+        .fill(0)
+        .map(() =>
+            Array(21)
+                .fill(0)
+                .map(() => Array(21).fill(-1)),
+        );
+    const b = dfs(0, 0, 10, true, true);
+    return a - b;
+}
+```
+
+### **...**
+
+```
+
+```
+
+<!-- tabs:end -->
diff --git a/solution/2800-2899/2827.Number of Beautiful Integers in the Range/README_EN.md b/solution/2800-2899/2827.Number of Beautiful Integers in the Range/README_EN.md
new file mode 100644
index 0000000000000..24f9944f47ee0
--- /dev/null
+++ b/solution/2800-2899/2827.Number of Beautiful Integers in the Range/README_EN.md	
@@ -0,0 +1,308 @@
+# [2827. Number of Beautiful Integers in the Range](https://leetcode.com/problems/number-of-beautiful-integers-in-the-range)
+
+[中文文档](/solution/2800-2899/2827.Number%20of%20Beautiful%20Integers%20in%20the%20Range/README.md)
+
+## Description
+
+<p>You are given positive integers <code>low</code>, <code>high</code>, and <code>k</code>.</p>
+
+<p>A number is <strong>beautiful</strong> if it meets both of the following conditions:</p>
+
+<ul>
+	<li>The count of even digits in the number is equal to the count of odd digits.</li>
+	<li>The number is divisible by <code>k</code>.</li>
+</ul>
+
+<p>Return <em>the number of beautiful integers in the range</em> <code>[low, high]</code>.</p>
+
+<p>&nbsp;</p>
+<p><strong class="example">Example 1:</strong></p>
+
+<pre>
+<strong>Input:</strong> low = 10, high = 20, k = 3
+<strong>Output:</strong> 2
+<strong>Explanation:</strong> There are 2 beautiful integers in the given range: [12,18]. 
+- 12 is beautiful because it contains 1 odd digit and 1 even digit, and is divisible by k = 3.
+- 18 is beautiful because it contains 1 odd digit and 1 even digit, and is divisible by k = 3.
+Additionally we can see that:
+- 16 is not beautiful because it is not divisible by k = 3.
+- 15 is not beautiful because it does not contain equal counts even and odd digits.
+It can be shown that there are only 2 beautiful integers in the given range.
+</pre>
+
+<p><strong class="example">Example 2:</strong></p>
+
+<pre>
+<strong>Input:</strong> low = 1, high = 10, k = 1
+<strong>Output:</strong> 1
+<strong>Explanation:</strong> There is 1 beautiful integer in the given range: [10].
+- 10 is beautiful because it contains 1 odd digit and 1 even digit, and is divisible by k = 1.
+It can be shown that there is only 1 beautiful integer in the given range.
+</pre>
+
+<p><strong class="example">Example 3:</strong></p>
+
+<pre>
+<strong>Input:</strong> low = 5, high = 5, k = 2
+<strong>Output:</strong> 0
+<strong>Explanation:</strong> There are 0 beautiful integers in the given range.
+- 5 is not beautiful because it is not divisible by k = 2 and it does not contain equal even and odd digits.
+</pre>
+
+<p>&nbsp;</p>
+<p><strong>Constraints:</strong></p>
+
+<ul>
+	<li><code>0 &lt; low &lt;= high &lt;= 10<sup>9</sup></code></li>
+	<li><code>0 &lt; k &lt;= 20</code></li>
+</ul>
+
+## Solutions
+
+<!-- tabs:start -->
+
+### **Python3**
+
+```python
+class Solution:
+    def numberOfBeautifulIntegers(self, low: int, high: int, k: int) -> int:
+        @cache
+        def dfs(pos: int, mod: int, diff: int, lead: int, limit: int) -> int:
+            if pos >= len(s):
+                return mod == 0 and diff == 10
+            up = int(s[pos]) if limit else 9
+            ans = 0
+            for i in range(up + 1):
+                if i == 0 and lead:
+                    ans += dfs(pos + 1, mod, diff, 1, limit and i == up)
+                else:
+                    nxt = diff + (1 if i % 2 == 1 else -1)
+                    ans += dfs(pos + 1, (mod * 10 + i) % k, nxt, 0, limit and i == up)
+            return ans
+
+        s = str(high)
+        a = dfs(0, 0, 10, 1, 1)
+        dfs.cache_clear()
+        s = str(low - 1)
+        b = dfs(0, 0, 10, 1, 1)
+        return a - b
+```
+
+### **Java**
+
+```java
+class Solution {
+    private String s;
+    private int k;
+    private Integer[][][] f = new Integer[11][21][21];
+
+    public int numberOfBeautifulIntegers(int low, int high, int k) {
+        this.k = k;
+        s = String.valueOf(high);
+        int a = dfs(0, 0, 10, true, true);
+        s = String.valueOf(low - 1);
+        f = new Integer[11][21][21];
+        int b = dfs(0, 0, 10, true, true);
+        return a - b;
+    }
+
+    private int dfs(int pos, int mod, int diff, boolean lead, boolean limit) {
+        if (pos >= s.length()) {
+            return mod == 0 && diff == 10 ? 1 : 0;
+        }
+        if (!lead && !limit && f[pos][mod][diff] != null) {
+            return f[pos][mod][diff];
+        }
+        int ans = 0;
+        int up = limit ? s.charAt(pos) - '0' : 9;
+        for (int i = 0; i <= up; ++i) {
+            if (i == 0 && lead) {
+                ans += dfs(pos + 1, mod, diff, true, limit && i == up);
+            } else {
+                int nxt = diff + (i % 2 == 1 ? 1 : -1);
+                ans += dfs(pos + 1, (mod * 10 + i) % k, nxt, false, limit && i == up);
+            }
+        }
+        if (!lead && !limit) {
+            f[pos][mod][diff] = ans;
+        }
+        return ans;
+    }
+}
+```
+
+### **C++**
+
+```cpp
+class Solution {
+public:
+    int numberOfBeautifulIntegers(int low, int high, int k) {
+        int f[11][21][21];
+        memset(f, -1, sizeof(f));
+        string s = to_string(high);
+
+        function<int(int, int, int, bool, bool)> dfs = [&](int pos, int mod, int diff, bool lead, bool limit) {
+            if (pos >= s.size()) {
+                return mod == 0 && diff == 10 ? 1 : 0;
+            }
+            if (!lead && !limit && f[pos][mod][diff] != -1) {
+                return f[pos][mod][diff];
+            }
+            int ans = 0;
+            int up = limit ? s[pos] - '0' : 9;
+            for (int i = 0; i <= up; ++i) {
+                if (i == 0 && lead) {
+                    ans += dfs(pos + 1, mod, diff, true, limit && i == up);
+                } else {
+                    int nxt = diff + (i % 2 == 1 ? 1 : -1);
+                    ans += dfs(pos + 1, (mod * 10 + i) % k, nxt, false, limit && i == up);
+                }
+            }
+            if (!lead && !limit) {
+                f[pos][mod][diff] = ans;
+            }
+            return ans;
+        };
+
+        int a = dfs(0, 0, 10, true, true);
+        memset(f, -1, sizeof(f));
+        s = to_string(low - 1);
+        int b = dfs(0, 0, 10, true, true);
+        return a - b;
+    }
+};
+```
+
+### **Go**
+
+```go
+func numberOfBeautifulIntegers(low int, high int, k int) int {
+	s := strconv.Itoa(high)
+	f := g(len(s), k, 21)
+
+	var dfs func(pos, mod, diff int, lead, limit bool) int
+	dfs = func(pos, mod, diff int, lead, limit bool) int {
+		if pos >= len(s) {
+			if mod == 0 && diff == 10 {
+				return 1
+			}
+			return 0
+		}
+		if !lead && !limit && f[pos][mod][diff] != -1 {
+			return f[pos][mod][diff]
+		}
+		up := 9
+		if limit {
+			up = int(s[pos] - '0')
+		}
+		ans := 0
+		for i := 0; i <= up; i++ {
+			if i == 0 && lead {
+				ans += dfs(pos+1, mod, diff, true, limit && i == up)
+			} else {
+				nxt := diff + 1
+				if i%2 == 0 {
+					nxt -= 2
+				}
+				ans += dfs(pos+1, (mod*10+i)%k, nxt, false, limit && i == up)
+			}
+		}
+		if !lead && !limit {
+			f[pos][mod][diff] = ans
+		}
+		return ans
+	}
+
+	a := dfs(0, 0, 10, true, true)
+	s = strconv.Itoa(low - 1)
+	f = g(len(s), k, 21)
+	b := dfs(0, 0, 10, true, true)
+	return a - b
+}
+
+func g(m, n, k int) [][][]int {
+	f := make([][][]int, m)
+	for i := 0; i < m; i++ {
+		f[i] = make([][]int, n)
+		for j := 0; j < n; j++ {
+			f[i][j] = make([]int, k)
+			for d := 0; d < k; d++ {
+				f[i][j][d] = -1
+			}
+		}
+	}
+	return f
+}
+```
+
+### **TypeScript**
+
+```ts
+function numberOfBeautifulIntegers(
+    low: number,
+    high: number,
+    k: number,
+): number {
+    let s = String(high);
+    let f: number[][][] = Array(11)
+        .fill(0)
+        .map(() =>
+            Array(21)
+                .fill(0)
+                .map(() => Array(21).fill(-1)),
+        );
+    const dfs = (
+        pos: number,
+        mod: number,
+        diff: number,
+        lead: boolean,
+        limit: boolean,
+    ): number => {
+        if (pos >= s.length) {
+            return mod == 0 && diff == 10 ? 1 : 0;
+        }
+        if (!lead && !limit && f[pos][mod][diff] != -1) {
+            return f[pos][mod][diff];
+        }
+        let ans = 0;
+        const up = limit ? Number(s[pos]) : 9;
+        for (let i = 0; i <= up; ++i) {
+            if (i === 0 && lead) {
+                ans += dfs(pos + 1, mod, diff, true, limit && i === up);
+            } else {
+                const nxt = diff + (i % 2 ? 1 : -1);
+                ans += dfs(
+                    pos + 1,
+                    (mod * 10 + i) % k,
+                    nxt,
+                    false,
+                    limit && i === up,
+                );
+            }
+        }
+        if (!lead && !limit) {
+            f[pos][mod][diff] = ans;
+        }
+        return ans;
+    };
+    const a = dfs(0, 0, 10, true, true);
+    s = String(low - 1);
+    f = Array(11)
+        .fill(0)
+        .map(() =>
+            Array(21)
+                .fill(0)
+                .map(() => Array(21).fill(-1)),
+        );
+    const b = dfs(0, 0, 10, true, true);
+    return a - b;
+}
+```
+
+### **...**
+
+```
+
+```
+
+<!-- tabs:end -->
diff --git a/solution/2800-2899/2827.Number of Beautiful Integers in the Range/Solution.cpp b/solution/2800-2899/2827.Number of Beautiful Integers in the Range/Solution.cpp
new file mode 100644
index 0000000000000..0a33f58f8e945
--- /dev/null
+++ b/solution/2800-2899/2827.Number of Beautiful Integers in the Range/Solution.cpp	
@@ -0,0 +1,37 @@
+class Solution {
+public:
+    int numberOfBeautifulIntegers(int low, int high, int k) {
+        int f[11][21][21];
+        memset(f, -1, sizeof(f));
+        string s = to_string(high);
+
+        function<int(int, int, int, bool, bool)> dfs = [&](int pos, int mod, int diff, bool lead, bool limit) {
+            if (pos >= s.size()) {
+                return mod == 0 && diff == 10 ? 1 : 0;
+            }
+            if (!lead && !limit && f[pos][mod][diff] != -1) {
+                return f[pos][mod][diff];
+            }
+            int ans = 0;
+            int up = limit ? s[pos] - '0' : 9;
+            for (int i = 0; i <= up; ++i) {
+                if (i == 0 && lead) {
+                    ans += dfs(pos + 1, mod, diff, true, limit && i == up);
+                } else {
+                    int nxt = diff + (i % 2 == 1 ? 1 : -1);
+                    ans += dfs(pos + 1, (mod * 10 + i) % k, nxt, false, limit && i == up);
+                }
+            }
+            if (!lead && !limit) {
+                f[pos][mod][diff] = ans;
+            }
+            return ans;
+        };
+
+        int a = dfs(0, 0, 10, true, true);
+        memset(f, -1, sizeof(f));
+        s = to_string(low - 1);
+        int b = dfs(0, 0, 10, true, true);
+        return a - b;
+    }
+};
\ No newline at end of file
diff --git a/solution/2800-2899/2827.Number of Beautiful Integers in the Range/Solution.go b/solution/2800-2899/2827.Number of Beautiful Integers in the Range/Solution.go
new file mode 100644
index 0000000000000..dc89d3497d164
--- /dev/null
+++ b/solution/2800-2899/2827.Number of Beautiful Integers in the Range/Solution.go	
@@ -0,0 +1,57 @@
+func numberOfBeautifulIntegers(low int, high int, k int) int {
+	s := strconv.Itoa(high)
+	f := g(len(s), k, 21)
+
+	var dfs func(pos, mod, diff int, lead, limit bool) int
+	dfs = func(pos, mod, diff int, lead, limit bool) int {
+		if pos >= len(s) {
+			if mod == 0 && diff == 10 {
+				return 1
+			}
+			return 0
+		}
+		if !lead && !limit && f[pos][mod][diff] != -1 {
+			return f[pos][mod][diff]
+		}
+		up := 9
+		if limit {
+			up = int(s[pos] - '0')
+		}
+		ans := 0
+		for i := 0; i <= up; i++ {
+			if i == 0 && lead {
+				ans += dfs(pos+1, mod, diff, true, limit && i == up)
+			} else {
+				nxt := diff + 1
+				if i%2 == 0 {
+					nxt -= 2
+				}
+				ans += dfs(pos+1, (mod*10+i)%k, nxt, false, limit && i == up)
+			}
+		}
+		if !lead && !limit {
+			f[pos][mod][diff] = ans
+		}
+		return ans
+	}
+
+	a := dfs(0, 0, 10, true, true)
+	s = strconv.Itoa(low - 1)
+	f = g(len(s), k, 21)
+	b := dfs(0, 0, 10, true, true)
+	return a - b
+}
+
+func g(m, n, k int) [][][]int {
+	f := make([][][]int, m)
+	for i := 0; i < m; i++ {
+		f[i] = make([][]int, n)
+		for j := 0; j < n; j++ {
+			f[i][j] = make([]int, k)
+			for d := 0; d < k; d++ {
+				f[i][j][d] = -1
+			}
+		}
+	}
+	return f
+}
\ No newline at end of file
diff --git a/solution/2800-2899/2827.Number of Beautiful Integers in the Range/Solution.java b/solution/2800-2899/2827.Number of Beautiful Integers in the Range/Solution.java
new file mode 100644
index 0000000000000..1ad5d40529f8a
--- /dev/null
+++ b/solution/2800-2899/2827.Number of Beautiful Integers in the Range/Solution.java	
@@ -0,0 +1,38 @@
+class Solution {
+    private String s;
+    private int k;
+    private Integer[][][] f = new Integer[11][21][21];
+
+    public int numberOfBeautifulIntegers(int low, int high, int k) {
+        this.k = k;
+        s = String.valueOf(high);
+        int a = dfs(0, 0, 10, true, true);
+        s = String.valueOf(low - 1);
+        f = new Integer[11][21][21];
+        int b = dfs(0, 0, 10, true, true);
+        return a - b;
+    }
+
+    private int dfs(int pos, int mod, int diff, boolean lead, boolean limit) {
+        if (pos >= s.length()) {
+            return mod == 0 && diff == 10 ? 1 : 0;
+        }
+        if (!lead && !limit && f[pos][mod][diff] != null) {
+            return f[pos][mod][diff];
+        }
+        int ans = 0;
+        int up = limit ? s.charAt(pos) - '0' : 9;
+        for (int i = 0; i <= up; ++i) {
+            if (i == 0 && lead) {
+                ans += dfs(pos + 1, mod, diff, true, limit && i == up);
+            } else {
+                int nxt = diff + (i % 2 == 1 ? 1 : -1);
+                ans += dfs(pos + 1, (mod * 10 + i) % k, nxt, false, limit && i == up);
+            }
+        }
+        if (!lead && !limit) {
+            f[pos][mod][diff] = ans;
+        }
+        return ans;
+    }
+}
\ No newline at end of file
diff --git a/solution/2800-2899/2827.Number of Beautiful Integers in the Range/Solution.py b/solution/2800-2899/2827.Number of Beautiful Integers in the Range/Solution.py
new file mode 100644
index 0000000000000..a307e421c4f92
--- /dev/null
+++ b/solution/2800-2899/2827.Number of Beautiful Integers in the Range/Solution.py	
@@ -0,0 +1,22 @@
+class Solution:
+    def numberOfBeautifulIntegers(self, low: int, high: int, k: int) -> int:
+        @cache
+        def dfs(pos: int, mod: int, diff: int, lead: int, limit: int) -> int:
+            if pos >= len(s):
+                return mod == 0 and diff == 10
+            up = int(s[pos]) if limit else 9
+            ans = 0
+            for i in range(up + 1):
+                if i == 0 and lead:
+                    ans += dfs(pos + 1, mod, diff, 1, limit and i == up)
+                else:
+                    nxt = diff + (1 if i % 2 == 1 else -1)
+                    ans += dfs(pos + 1, (mod * 10 + i) % k, nxt, 0, limit and i == up)
+            return ans
+
+        s = str(high)
+        a = dfs(0, 0, 10, 1, 1)
+        dfs.cache_clear()
+        s = str(low - 1)
+        b = dfs(0, 0, 10, 1, 1)
+        return a - b
diff --git a/solution/2800-2899/2827.Number of Beautiful Integers in the Range/Solution.ts b/solution/2800-2899/2827.Number of Beautiful Integers in the Range/Solution.ts
new file mode 100644
index 0000000000000..1cc45fdc1e981
--- /dev/null
+++ b/solution/2800-2899/2827.Number of Beautiful Integers in the Range/Solution.ts	
@@ -0,0 +1,59 @@
+function numberOfBeautifulIntegers(
+    low: number,
+    high: number,
+    k: number,
+): number {
+    let s = String(high);
+    let f: number[][][] = Array(11)
+        .fill(0)
+        .map(() =>
+            Array(21)
+                .fill(0)
+                .map(() => Array(21).fill(-1)),
+        );
+    const dfs = (
+        pos: number,
+        mod: number,
+        diff: number,
+        lead: boolean,
+        limit: boolean,
+    ): number => {
+        if (pos >= s.length) {
+            return mod == 0 && diff == 10 ? 1 : 0;
+        }
+        if (!lead && !limit && f[pos][mod][diff] != -1) {
+            return f[pos][mod][diff];
+        }
+        let ans = 0;
+        const up = limit ? Number(s[pos]) : 9;
+        for (let i = 0; i <= up; ++i) {
+            if (i === 0 && lead) {
+                ans += dfs(pos + 1, mod, diff, true, limit && i === up);
+            } else {
+                const nxt = diff + (i % 2 ? 1 : -1);
+                ans += dfs(
+                    pos + 1,
+                    (mod * 10 + i) % k,
+                    nxt,
+                    false,
+                    limit && i === up,
+                );
+            }
+        }
+        if (!lead && !limit) {
+            f[pos][mod][diff] = ans;
+        }
+        return ans;
+    };
+    const a = dfs(0, 0, 10, true, true);
+    s = String(low - 1);
+    f = Array(11)
+        .fill(0)
+        .map(() =>
+            Array(21)
+                .fill(0)
+                .map(() => Array(21).fill(-1)),
+        );
+    const b = dfs(0, 0, 10, true, true);
+    return a - b;
+}
diff --git a/solution/2800-2899/2828.Check if a String Is an Acronym of Words/README.md b/solution/2800-2899/2828.Check if a String Is an Acronym of Words/README.md
new file mode 100644
index 0000000000000..4929bce998be1
--- /dev/null
+++ b/solution/2800-2899/2828.Check if a String Is an Acronym of Words/README.md	
@@ -0,0 +1,134 @@
+# [2828. 判别首字母缩略词](https://leetcode.cn/problems/check-if-a-string-is-an-acronym-of-words)
+
+[English Version](/solution/2800-2899/2828.Check%20if%20a%20String%20Is%20an%20Acronym%20of%20Words/README_EN.md)
+
+## 题目描述
+
+<!-- 这里写题目描述 -->
+
+<p>给你一个字符串数组&nbsp;<code>words</code> 和一个字符串 <code>s</code> ,请你判断 <code>s</code> 是不是 <code>words</code> 的 <strong>首字母缩略词</strong> 。</p>
+
+<p>如果可以按顺序串联 <code>words</code> 中每个字符串的第一个字符形成字符串 <code>s</code> ,则认为 <code>s</code> 是 <code>words</code> 的首字母缩略词。例如,<code>"ab"</code> 可以由 <code>["apple", "banana"]</code> 形成,但是无法从 <code>["bear", "aardvark"]</code> 形成。</p>
+
+<p>如果 <code>s</code> 是 <code>words</code> 的首字母缩略词,返回 <code>true</code><em> </em>;否则,返回<em> </em><code>false</code> 。</p>
+
+<p>&nbsp;</p>
+
+<p><strong class="example">示例 1:</strong></p>
+
+<pre>
+<strong>输入:</strong>words = ["alice","bob","charlie"], s = "abc"
+<strong>输出:</strong>true
+<strong>解释:</strong>words 中 "alice"、"bob" 和 "charlie" 的第一个字符分别是 'a'、'b' 和 'c'。因此,s = "abc" 是首字母缩略词。 
+</pre>
+
+<p><strong class="example">示例 2:</strong></p>
+
+<pre>
+<strong>输入:</strong>words = ["an","apple"], s = "a"
+<strong>输出:</strong>false
+<strong>解释:</strong>words 中 "an" 和 "apple" 的第一个字符分别是 'a' 和 'a'。
+串联这些字符形成的首字母缩略词是 "aa" 。
+因此,s = "a" 不是首字母缩略词。
+</pre>
+
+<p><strong class="example">示例 3:</strong></p>
+
+<pre>
+<strong>输入:</strong>words = ["never","gonna","give","up","on","you"], s = "ngguoy"
+<strong>输出:</strong>true
+<strong>解释:</strong>串联数组 words 中每个字符串的第一个字符,得到字符串 "ngguoy" 。
+因此,s = "ngguoy" 是首字母缩略词。 
+</pre>
+
+<p>&nbsp;</p>
+
+<p><strong>提示:</strong></p>
+
+<ul>
+	<li><code>1 &lt;= words.length &lt;= 100</code></li>
+	<li><code>1 &lt;= words[i].length &lt;= 10</code></li>
+	<li><code>1 &lt;= s.length &lt;= 100</code></li>
+	<li><code>words[i]</code> 和 <code>s</code> 由小写英文字母组成</li>
+</ul>
+
+## 解法
+
+<!-- 这里可写通用的实现逻辑 -->
+
+**方法一:模拟**
+
+我们可以遍历数组 $words$ 中的每个字符串,将其首字母拼接起来,得到一个新的字符串 $t$,然后判断 $t$ 是否等于 $s$ 即可。
+
+时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 $words$ 的长度。
+
+<!-- tabs:start -->
+
+### **Python3**
+
+<!-- 这里可写当前语言的特殊实现逻辑 -->
+
+```python
+class Solution:
+    def isAcronym(self, words: List[str], s: str) -> bool:
+        return "".join(w[0] for w in words) == s
+```
+
+### **Java**
+
+<!-- 这里可写当前语言的特殊实现逻辑 -->
+
+```java
+class Solution {
+    public boolean isAcronym(List<String> words, String s) {
+        StringBuilder t = new StringBuilder();
+        for (var w : words) {
+            t.append(w.charAt(0));
+        }
+        return t.toString().equals(s);
+    }
+}
+```
+
+### **C++**
+
+```cpp
+class Solution {
+public:
+    bool isAcronym(vector<string>& words, string s) {
+        string t;
+        for (auto& w : words) {
+            t += w[0];
+        }
+        return t == s;
+    }
+};
+```
+
+### **Go**
+
+```go
+func isAcronym(words []string, s string) bool {
+	t := []byte{}
+	for _, w := range words {
+		t = append(t, w[0])
+	}
+	return string(t) == s
+}
+```
+
+### **TypeScript**
+
+```ts
+function isAcronym(words: string[], s: string): boolean {
+    return words.map(w => w[0]).join('') === s;
+}
+```
+
+### **...**
+
+```
+
+```
+
+<!-- tabs:end -->
diff --git a/solution/2800-2899/2828.Check if a String Is an Acronym of Words/README_EN.md b/solution/2800-2899/2828.Check if a String Is an Acronym of Words/README_EN.md
new file mode 100644
index 0000000000000..9304b5dddcaae
--- /dev/null
+++ b/solution/2800-2899/2828.Check if a String Is an Acronym of Words/README_EN.md	
@@ -0,0 +1,118 @@
+# [2828. Check if a String Is an Acronym of Words](https://leetcode.com/problems/check-if-a-string-is-an-acronym-of-words)
+
+[中文文档](/solution/2800-2899/2828.Check%20if%20a%20String%20Is%20an%20Acronym%20of%20Words/README.md)
+
+## Description
+
+<p>Given an array of strings <code>words</code> and a string <code>s</code>, determine if <code>s</code> is an <strong>acronym</strong> of words.</p>
+
+<p>The string <code>s</code> is considered an acronym of <code>words</code> if it can be formed by concatenating the <strong>first</strong> character of each string in <code>words</code> <strong>in order</strong>. For example, <code>&quot;ab&quot;</code> can be formed from <code>[&quot;apple&quot;, &quot;banana&quot;]</code>, but it can&#39;t be formed from <code>[&quot;bear&quot;, &quot;aardvark&quot;]</code>.</p>
+
+<p>Return <code>true</code><em> if </em><code>s</code><em> is an acronym of </em><code>words</code><em>, and </em><code>false</code><em> otherwise. </em></p>
+
+<p>&nbsp;</p>
+<p><strong class="example">Example 1:</strong></p>
+
+<pre>
+<strong>Input:</strong> words = [&quot;alice&quot;,&quot;bob&quot;,&quot;charlie&quot;], s = &quot;abc&quot;
+<strong>Output:</strong> true
+<strong>Explanation:</strong> The first character in the words &quot;alice&quot;, &quot;bob&quot;, and &quot;charlie&quot; are &#39;a&#39;, &#39;b&#39;, and &#39;c&#39;, respectively. Hence, s = &quot;abc&quot; is the acronym. 
+</pre>
+
+<p><strong class="example">Example 2:</strong></p>
+
+<pre>
+<strong>Input:</strong> words = [&quot;an&quot;,&quot;apple&quot;], s = &quot;a&quot;
+<strong>Output:</strong> false
+<strong>Explanation:</strong> The first character in the words &quot;an&quot; and &quot;apple&quot; are &#39;a&#39; and &#39;a&#39;, respectively. 
+The acronym formed by concatenating these characters is &quot;aa&quot;. 
+Hence, s = &quot;a&quot; is not the acronym.
+</pre>
+
+<p><strong class="example">Example 3:</strong></p>
+
+<pre>
+<strong>Input:</strong> words = [&quot;never&quot;,&quot;gonna&quot;,&quot;give&quot;,&quot;up&quot;,&quot;on&quot;,&quot;you&quot;], s = &quot;ngguoy&quot;
+<strong>Output:</strong> true
+<strong>Explanation: </strong>By concatenating the first character of the words in the array, we get the string &quot;ngguoy&quot;. 
+Hence, s = &quot;ngguoy&quot; is the acronym.
+</pre>
+
+<p>&nbsp;</p>
+<p><strong>Constraints:</strong></p>
+
+<ul>
+	<li><code>1 &lt;= words.length &lt;= 100</code></li>
+	<li><code>1 &lt;= words[i].length &lt;= 10</code></li>
+	<li><code>1 &lt;= s.length &lt;= 100</code></li>
+	<li><code>words[i]</code> and <code>s</code> consist of lowercase English letters.</li>
+</ul>
+
+## Solutions
+
+<!-- tabs:start -->
+
+### **Python3**
+
+```python
+class Solution:
+    def isAcronym(self, words: List[str], s: str) -> bool:
+        return "".join(w[0] for w in words) == s
+```
+
+### **Java**
+
+```java
+class Solution {
+    public boolean isAcronym(List<String> words, String s) {
+        StringBuilder t = new StringBuilder();
+        for (var w : words) {
+            t.append(w.charAt(0));
+        }
+        return t.toString().equals(s);
+    }
+}
+```
+
+### **C++**
+
+```cpp
+class Solution {
+public:
+    bool isAcronym(vector<string>& words, string s) {
+        string t;
+        for (auto& w : words) {
+            t += w[0];
+        }
+        return t == s;
+    }
+};
+```
+
+### **Go**
+
+```go
+func isAcronym(words []string, s string) bool {
+	t := []byte{}
+	for _, w := range words {
+		t = append(t, w[0])
+	}
+	return string(t) == s
+}
+```
+
+### **TypeScript**
+
+```ts
+function isAcronym(words: string[], s: string): boolean {
+    return words.map(w => w[0]).join('') === s;
+}
+```
+
+### **...**
+
+```
+
+```
+
+<!-- tabs:end -->
diff --git a/solution/2800-2899/2828.Check if a String Is an Acronym of Words/Solution.cpp b/solution/2800-2899/2828.Check if a String Is an Acronym of Words/Solution.cpp
new file mode 100644
index 0000000000000..eda07254e5097
--- /dev/null
+++ b/solution/2800-2899/2828.Check if a String Is an Acronym of Words/Solution.cpp	
@@ -0,0 +1,10 @@
+class Solution {
+public:
+    bool isAcronym(vector<string>& words, string s) {
+        string t;
+        for (auto& w : words) {
+            t += w[0];
+        }
+        return t == s;
+    }
+};
\ No newline at end of file
diff --git a/solution/2800-2899/2828.Check if a String Is an Acronym of Words/Solution.go b/solution/2800-2899/2828.Check if a String Is an Acronym of Words/Solution.go
new file mode 100644
index 0000000000000..5c562df36c0b7
--- /dev/null
+++ b/solution/2800-2899/2828.Check if a String Is an Acronym of Words/Solution.go	
@@ -0,0 +1,7 @@
+func isAcronym(words []string, s string) bool {
+	t := []byte{}
+	for _, w := range words {
+		t = append(t, w[0])
+	}
+	return string(t) == s
+}
\ No newline at end of file
diff --git a/solution/2800-2899/2828.Check if a String Is an Acronym of Words/Solution.java b/solution/2800-2899/2828.Check if a String Is an Acronym of Words/Solution.java
new file mode 100644
index 0000000000000..627c1d33530ad
--- /dev/null
+++ b/solution/2800-2899/2828.Check if a String Is an Acronym of Words/Solution.java	
@@ -0,0 +1,9 @@
+class Solution {
+    public boolean isAcronym(List<String> words, String s) {
+        StringBuilder t = new StringBuilder();
+        for (var w : words) {
+            t.append(w.charAt(0));
+        }
+        return t.toString().equals(s);
+    }
+}
\ No newline at end of file
diff --git a/solution/2800-2899/2828.Check if a String Is an Acronym of Words/Solution.py b/solution/2800-2899/2828.Check if a String Is an Acronym of Words/Solution.py
new file mode 100644
index 0000000000000..3337eb558751d
--- /dev/null
+++ b/solution/2800-2899/2828.Check if a String Is an Acronym of Words/Solution.py	
@@ -0,0 +1,3 @@
+class Solution:
+    def isAcronym(self, words: List[str], s: str) -> bool:
+        return "".join(w[0] for w in words) == s
diff --git a/solution/2800-2899/2828.Check if a String Is an Acronym of Words/Solution.ts b/solution/2800-2899/2828.Check if a String Is an Acronym of Words/Solution.ts
new file mode 100644
index 0000000000000..a1ef3f8a24b8d
--- /dev/null
+++ b/solution/2800-2899/2828.Check if a String Is an Acronym of Words/Solution.ts	
@@ -0,0 +1,3 @@
+function isAcronym(words: string[], s: string): boolean {
+    return words.map(w => w[0]).join('') === s;
+}
diff --git a/solution/2800-2899/2829.Determine the Minimum Sum of a k-avoiding Array/README.md b/solution/2800-2899/2829.Determine the Minimum Sum of a k-avoiding Array/README.md
new file mode 100644
index 0000000000000..54b098ebfdf2d
--- /dev/null
+++ b/solution/2800-2899/2829.Determine the Minimum Sum of a k-avoiding Array/README.md	
@@ -0,0 +1,168 @@
+# [2829. k-avoiding 数组的最小总和](https://leetcode.cn/problems/determine-the-minimum-sum-of-a-k-avoiding-array)
+
+[English Version](/solution/2800-2899/2829.Determine%20the%20Minimum%20Sum%20of%20a%20k-avoiding%20Array/README_EN.md)
+
+## 题目描述
+
+<!-- 这里写题目描述 -->
+
+<p>给你两个整数 <code>n</code> 和 <code>k</code> 。</p>
+
+<p>对于一个由 <strong>不同</strong> 正整数组成的数组,如果其中不存在任何求和等于 k 的不同元素对,则称其为 <strong>k-avoiding</strong> 数组。</p>
+
+<p>返回长度为 <code>n</code> 的 <strong>k-avoiding</strong> 数组的可能的最小总和。</p>
+
+<p>&nbsp;</p>
+
+<p><strong class="example">示例 1:</strong></p>
+
+<pre>
+<strong>输入:</strong>n = 5, k = 4
+<strong>输出:</strong>18
+<strong>解释:</strong>设若 k-avoiding 数组为 [1,2,4,5,6] ,其元素总和为 18 。
+可以证明不存在总和小于 18 的 k-avoiding 数组。
+</pre>
+
+<p><strong class="example">示例 2:</strong></p>
+
+<pre>
+<strong>输入:</strong>n = 2, k = 6
+<strong>输出:</strong>3
+<strong>解释:</strong>可以构造数组 [1,2] ,其元素总和为 3 。
+可以证明不存在总和小于 3 的 k-avoiding 数组。 
+</pre>
+
+<p>&nbsp;</p>
+
+<p><strong>提示:</strong></p>
+
+<ul>
+	<li><code>1 &lt;= n, k &lt;= 50</code></li>
+</ul>
+
+## 解法
+
+<!-- 这里可写通用的实现逻辑 -->
+
+**方法一:贪心 + 模拟**
+
+我们从正整数 $i=1$ 开始,依次判断 $i$ 是否可以加入数组中,如果可以加入,则将 $i$ 加入数组中,累加到答案中,然后将 $k-i$ 置为已访问,表示 $k-i$ 不能加入数组中。循环直到数组长度为 $n$。
+
+时间复杂度 $O(n^2)$,空间复杂度 $O(n^2)$。其中 $n$ 为数组长度。
+
+<!-- tabs:start -->
+
+### **Python3**
+
+<!-- 这里可写当前语言的特殊实现逻辑 -->
+
+```python
+class Solution:
+    def minimumSum(self, n: int, k: int) -> int:
+        s, i = 0, 1
+        vis = set()
+        for _ in range(n):
+            while i in vis:
+                i += 1
+            vis.add(i)
+            vis.add(k - i)
+            s += i
+        return s
+```
+
+### **Java**
+
+<!-- 这里可写当前语言的特殊实现逻辑 -->
+
+```java
+class Solution {
+    public int minimumSum(int n, int k) {
+        int s = 0, i = 1;
+        boolean[] vis = new boolean[k + n * n + 1];
+        while (n-- > 0) {
+            while (vis[i]) {
+                ++i;
+            }
+            vis[i] = true;
+            if (k >= i) {
+                vis[k - i] = true;
+            }
+            s += i;
+        }
+        return s;
+    }
+}
+```
+
+### **C++**
+
+```cpp
+class Solution {
+public:
+    int minimumSum(int n, int k) {
+        int s = 0, i = 1;
+        bool vis[k + n * n + 1];
+        memset(vis, false, sizeof(vis));
+        while (n--) {
+            while (vis[i]) {
+                ++i;
+            }
+            vis[i] = true;
+            if (k >= i) {
+                vis[k - i] = true;
+            }
+            s += i;
+        }
+        return s;
+    }
+};
+```
+
+### **Go**
+
+```go
+func minimumSum(n int, k int) int {
+	s, i := 0, 1
+	vis := make([]bool, k+n*n+1)
+	for ; n > 0; n-- {
+		for vis[i] {
+			i++
+		}
+		vis[i] = true
+		if k >= i {
+			vis[k-i] = true
+		}
+		s += i
+	}
+	return s
+}
+```
+
+### **TypeScript**
+
+```ts
+function minimumSum(n: number, k: number): number {
+    let s = 0;
+    let i = 1;
+    const vis: boolean[] = Array(n * n + k + 1);
+    while (n--) {
+        while (vis[i]) {
+            ++i;
+        }
+        vis[i] = true;
+        if (k >= i) {
+            vis[k - i] = true;
+        }
+        s += i;
+    }
+    return s;
+}
+```
+
+### **...**
+
+```
+
+```
+
+<!-- tabs:end -->
diff --git a/solution/2800-2899/2829.Determine the Minimum Sum of a k-avoiding Array/README_EN.md b/solution/2800-2899/2829.Determine the Minimum Sum of a k-avoiding Array/README_EN.md
new file mode 100644
index 0000000000000..179e4c900bc1b
--- /dev/null
+++ b/solution/2800-2899/2829.Determine the Minimum Sum of a k-avoiding Array/README_EN.md	
@@ -0,0 +1,152 @@
+# [2829. Determine the Minimum Sum of a k-avoiding Array](https://leetcode.com/problems/determine-the-minimum-sum-of-a-k-avoiding-array)
+
+[中文文档](/solution/2800-2899/2829.Determine%20the%20Minimum%20Sum%20of%20a%20k-avoiding%20Array/README.md)
+
+## Description
+
+<p>You are given two integers,&nbsp;<code>n</code> and <code>k</code>.</p>
+
+<p>An array of <strong>distinct</strong> positive integers is called a <b>k-avoiding</b> array if there does not exist any pair of distinct elements that sum to <code>k</code>.</p>
+
+<p>Return <em>the <strong>minimum</strong> possible sum of a k-avoiding array of length </em><code>n</code>.</p>
+
+<p>&nbsp;</p>
+<p><strong class="example">Example 1:</strong></p>
+
+<pre>
+<strong>Input:</strong> n = 5, k = 4
+<strong>Output:</strong> 18
+<strong>Explanation:</strong> Consider the k-avoiding array [1,2,4,5,6], which has a sum of 18.
+It can be proven that there is no k-avoiding array with a sum less than 18.
+</pre>
+
+<p><strong class="example">Example 2:</strong></p>
+
+<pre>
+<strong>Input:</strong> n = 2, k = 6
+<strong>Output:</strong> 3
+<strong>Explanation:</strong> We can construct the array [1,2], which has a sum of 3.
+It can be proven that there is no k-avoiding array with a sum less than 3.
+</pre>
+
+<p>&nbsp;</p>
+<p><strong>Constraints:</strong></p>
+
+<ul>
+	<li><code>1 &lt;= n, k &lt;= 50</code></li>
+</ul>
+
+## Solutions
+
+<!-- tabs:start -->
+
+### **Python3**
+
+```python
+class Solution:
+    def minimumSum(self, n: int, k: int) -> int:
+        s, i = 0, 1
+        vis = set()
+        for _ in range(n):
+            while i in vis:
+                i += 1
+            vis.add(i)
+            vis.add(k - i)
+            s += i
+        return s
+```
+
+### **Java**
+
+```java
+class Solution {
+    public int minimumSum(int n, int k) {
+        int s = 0, i = 1;
+        boolean[] vis = new boolean[k + n * n + 1];
+        while (n-- > 0) {
+            while (vis[i]) {
+                ++i;
+            }
+            vis[i] = true;
+            if (k >= i) {
+                vis[k - i] = true;
+            }
+            s += i;
+        }
+        return s;
+    }
+}
+```
+
+### **C++**
+
+```cpp
+class Solution {
+public:
+    int minimumSum(int n, int k) {
+        int s = 0, i = 1;
+        bool vis[k + n * n + 1];
+        memset(vis, false, sizeof(vis));
+        while (n--) {
+            while (vis[i]) {
+                ++i;
+            }
+            vis[i] = true;
+            if (k >= i) {
+                vis[k - i] = true;
+            }
+            s += i;
+        }
+        return s;
+    }
+};
+```
+
+### **Go**
+
+```go
+func minimumSum(n int, k int) int {
+	s, i := 0, 1
+	vis := make([]bool, k+n*n+1)
+	for ; n > 0; n-- {
+		for vis[i] {
+			i++
+		}
+		vis[i] = true
+		if k >= i {
+			vis[k-i] = true
+		}
+		s += i
+	}
+	return s
+}
+```
+
+### **TypeScript**
+
+```ts
+function minimumSum(n: number, k: number): number {
+    let s = 0;
+    let i = 1;
+    const vis: boolean[] = Array(n * n + k + 1);
+    while (n--) {
+        while (vis[i]) {
+            ++i;
+        }
+        vis[i] = true;
+        if (k >= i) {
+            vis[k - i] = true;
+        }
+        s += i;
+    }
+    return s;
+}
+```
+
+### **...**
+
+```
+
+```
+
+<!-- tabs:end -->
diff --git a/solution/2800-2899/2829.Determine the Minimum Sum of a k-avoiding Array/Solution.cpp b/solution/2800-2899/2829.Determine the Minimum Sum of a k-avoiding Array/Solution.cpp
new file mode 100644
index 0000000000000..b9602dd6233f1
--- /dev/null
+++ b/solution/2800-2899/2829.Determine the Minimum Sum of a k-avoiding Array/Solution.cpp	
@@ -0,0 +1,19 @@
+class Solution {
+public:
+    int minimumSum(int n, int k) {
+        int s = 0, i = 1;
+        bool vis[k + n * n + 1];
+        memset(vis, false, sizeof(vis));
+        while (n--) {
+            while (vis[i]) {
+                ++i;
+            }
+            vis[i] = true;
+            if (k >= i) {
+                vis[k - i] = true;
+            }
+            s += i;
+        }
+        return s;
+    }
+};
\ No newline at end of file
diff --git a/solution/2800-2899/2829.Determine the Minimum Sum of a k-avoiding Array/Solution.go b/solution/2800-2899/2829.Determine the Minimum Sum of a k-avoiding Array/Solution.go
new file mode 100644
index 0000000000000..3ceacec441460
--- /dev/null
+++ b/solution/2800-2899/2829.Determine the Minimum Sum of a k-avoiding Array/Solution.go	
@@ -0,0 +1,15 @@
+func minimumSum(n int, k int) int {
+	s, i := 0, 1
+	vis := make([]bool, k+n*n+1)
+	for ; n > 0; n-- {
+		for vis[i] {
+			i++
+		}
+		vis[i] = true
+		if k >= i {
+			vis[k-i] = true
+		}
+		s += i
+	}
+	return s
+}
\ No newline at end of file
diff --git a/solution/2800-2899/2829.Determine the Minimum Sum of a k-avoiding Array/Solution.java b/solution/2800-2899/2829.Determine the Minimum Sum of a k-avoiding Array/Solution.java
new file mode 100644
index 0000000000000..73a2284dad786
--- /dev/null
+++ b/solution/2800-2899/2829.Determine the Minimum Sum of a k-avoiding Array/Solution.java	
@@ -0,0 +1,17 @@
+class Solution {
+    public int minimumSum(int n, int k) {
+        int s = 0, i = 1;
+        boolean[] vis = new boolean[k + n * n + 1];
+        while (n-- > 0) {
+            while (vis[i]) {
+                ++i;
+            }
+            vis[i] = true;
+            if (k >= i) {
+                vis[k - i] = true;
+            }
+            s += i;
+        }
+        return s;
+    }
+}
\ No newline at end of file
diff --git a/solution/2800-2899/2829.Determine the Minimum Sum of a k-avoiding Array/Solution.py b/solution/2800-2899/2829.Determine the Minimum Sum of a k-avoiding Array/Solution.py
new file mode 100644
index 0000000000000..4594f3166f2fa
--- /dev/null
+++ b/solution/2800-2899/2829.Determine the Minimum Sum of a k-avoiding Array/Solution.py	
@@ -0,0 +1,11 @@
+class Solution:
+    def minimumSum(self, n: int, k: int) -> int:
+        s, i = 0, 1
+        vis = set()
+        for _ in range(n):
+            while i in vis:
+                i += 1
+            vis.add(i)
+            vis.add(k - i)
+            s += i
+        return s
diff --git a/solution/2800-2899/2829.Determine the Minimum Sum of a k-avoiding Array/Solution.ts b/solution/2800-2899/2829.Determine the Minimum Sum of a k-avoiding Array/Solution.ts
new file mode 100644
index 0000000000000..75407c9881b83
--- /dev/null
+++ b/solution/2800-2899/2829.Determine the Minimum Sum of a k-avoiding Array/Solution.ts	
@@ -0,0 +1,16 @@
+function minimumSum(n: number, k: number): number {
+    let s = 0;
+    let i = 1;
+    const vis: boolean[] = Array(n * n + k + 1);
+    while (n--) {
+        while (vis[i]) {
+            ++i;
+        }
+        vis[i] = true;
+        if (k >= i) {
+            vis[k - i] = true;
+        }
+        s += i;
+    }
+    return s;
+}
diff --git a/solution/2800-2899/2830.Maximize the Profit as the Salesman/README.md b/solution/2800-2899/2830.Maximize the Profit as the Salesman/README.md
new file mode 100644
index 0000000000000..e8ff6dddcc507
--- /dev/null
+++ b/solution/2800-2899/2830.Maximize the Profit as the Salesman/README.md	
@@ -0,0 +1,207 @@
+# [2830. 销售利润最大化](https://leetcode.cn/problems/maximize-the-profit-as-the-salesman)
+
+[English Version](/solution/2800-2899/2830.Maximize%20the%20Profit%20as%20the%20Salesman/README_EN.md)
+
+## 题目描述
+
+<!-- 这里写题目描述 -->
+
+<p>给你一个整数 <code>n</code> 表示数轴上的房屋数量,编号从 <code>0</code> 到 <code>n - 1</code> 。</p>
+
+<p>另给你一个二维整数数组 <code>offers</code> ,其中 <code>offers[i] = [start<sub>i</sub>, end<sub>i</sub>, gold<sub>i</sub>]</code> 表示第 <code>i</code> 个买家想要以 <code>gold<sub>i</sub></code> 枚金币的价格购买从 <code>start<sub>i</sub></code> 到 <code>end<sub>i</sub></code> 的所有房屋。</p>
+
+<p>作为一名销售,你需要有策略地选择并销售房屋使自己的收入最大化。</p>
+
+<p>返回你可以赚取的金币的最大数目。</p>
+
+<p><strong>注意</strong> 同一所房屋不能卖给不同的买家,并且允许保留一些房屋不进行出售。</p>
+
+<p>&nbsp;</p>
+
+<p><strong class="example">示例 1:</strong></p>
+
+<pre>
+<strong>输入:</strong>n = 5, offers = [[0,0,1],[0,2,2],[1,3,2]]
+<strong>输出:</strong>3
+<strong>解释:</strong>
+有 5 所房屋,编号从 0 到 4 ,共有 3 个购买要约。
+将位于 [0,0] 范围内的房屋以 1 金币的价格出售给第 1 位买家,并将位于 [1,3] 范围内的房屋以 2 金币的价格出售给第 3 位买家。
+可以证明我们最多只能获得 3 枚金币。</pre>
+
+<p><strong class="example">示例 2:</strong></p>
+
+<pre>
+<strong>输入:</strong>n = 5, offers = [[0,0,1],[0,2,10],[1,3,2]]
+<strong>输出:</strong>10
+<strong>解释:</strong>有 5 所房屋,编号从 0 到 4 ,共有 3 个购买要约。
+将位于 [0,2] 范围内的房屋以 10 金币的价格出售给第 2 位买家。
+可以证明我们最多只能获得 10 枚金币。</pre>
+
+<p>&nbsp;</p>
+
+<p><strong>提示:</strong></p>
+
+<ul>
+	<li><code>1 &lt;= n &lt;= 10<sup>5</sup></code></li>
+	<li><code>1 &lt;= offers.length &lt;= 10<sup>5</sup></code></li>
+	<li><code>offers[i].length == 3</code></li>
+	<li><code>0 &lt;= start<sub>i</sub> &lt;= end<sub>i</sub> &lt;= n - 1</code></li>
+	<li><code>1 &lt;= gold<sub>i</sub> &lt;= 10<sup>3</sup></code></li>
+</ul>
+
+## 解法
+
+<!-- 这里可写通用的实现逻辑 -->
+
+**方法一:排序 + 二分查找 + 动态规划**
+
+我们将所有的购买要约按照 $end$ 从小到大排序,然后使用动态规划求解。
+
+定义 $f[i]$ 表示前 $i$ 个购买要约中,我们可以获得的最大金币数。答案即为 $f[n]$。
+
+对于 $f[i]$,我们可以选择不卖出第 $i$ 个购买要约,此时 $f[i] = f[i - 1]$;也可以选择卖出第 $i$ 个购买要约,此时 $f[i] = f[j] + gold_i$,其中 $j$ 是满足 $end_j \leq start_i$ 的最大下标。
+
+时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 是购买要约的数量。
+
+<!-- tabs:start -->
+
+### **Python3**
+
+<!-- 这里可写当前语言的特殊实现逻辑 -->
+
+```python
+class Solution:
+    def maximizeTheProfit(self, n: int, offers: List[List[int]]) -> int:
+        offers.sort(key=lambda x: x[1])
+        f = [0] * (len(offers) + 1)
+        g = [x[1] for x in offers]
+        for i, (s, _, v) in enumerate(offers, 1):
+            j = bisect_left(g, s)
+            f[i] = max(f[i - 1], f[j] + v)
+        return f[-1]
+```
+
+### **Java**
+
+<!-- 这里可写当前语言的特殊实现逻辑 -->
+
+```java
+class Solution {
+    public int maximizeTheProfit(int n, List<List<Integer>> offers) {
+        offers.sort((a, b) -> a.get(1) - b.get(1));
+        n = offers.size();
+        int[] f = new int[n + 1];
+        int[] g = new int[n];
+        for (int i = 0; i < n; ++i) {
+            g[i] = offers.get(i).get(1);
+        }
+        for (int i = 1; i <= n; ++i) {
+            var o = offers.get(i - 1);
+            int j = search(g, o.get(0));
+            f[i] = Math.max(f[i - 1], f[j] + o.get(2));
+        }
+        return f[n];
+    }
+
+    private int search(int[] nums, int x) {
+        int l = 0, r = nums.length;
+        while (l < r) {
+            int mid = (l + r) >> 1;
+            if (nums[mid] >= x) {
+                r = mid;
+            } else {
+                l = mid + 1;
+            }
+        }
+        return l;
+    }
+}
+```
+
+### **C++**
+
+```cpp
+class Solution {
+public:
+    int maximizeTheProfit(int n, vector<vector<int>>& offers) {
+        sort(offers.begin(), offers.end(), [](const vector<int>& a, const vector<int>& b) {
+            return a[1] < b[1];
+        });
+        n = offers.size();
+        vector<int> f(n + 1);
+        vector<int> g;
+        for (auto& o : offers) {
+            g.push_back(o[1]);
+        }
+        for (int i = 1; i <= n; ++i) {
+            auto o = offers[i - 1];
+            int j = lower_bound(g.begin(), g.end(), o[0]) - g.begin();
+            f[i] = max(f[i - 1], f[j] + o[2]);
+        }
+        return f[n];
+    }
+};
+```
+
+### **Go**
+
+```go
+func maximizeTheProfit(n int, offers [][]int) int {
+	sort.Slice(offers, func(i, j int) bool { return offers[i][1] < offers[j][1] })
+	n = len(offers)
+	f := make([]int, n+1)
+	g := []int{}
+	for _, o := range offers {
+		g = append(g, o[1])
+	}
+	for i := 1; i <= n; i++ {
+		j := sort.SearchInts(g, offers[i-1][0])
+		f[i] = max(f[i-1], f[j]+offers[i-1][2])
+	}
+	return f[n]
+}
+
+func max(a, b int) int {
+	if a > b {
+		return a
+	}
+	return b
+}
+```
+
+### **TypeScript**
+
+```ts
+function maximizeTheProfit(n: number, offers: number[][]): number {
+    offers.sort((a, b) => a[1] - b[1]);
+    n = offers.length;
+    const f: number[] = Array(n + 1).fill(0);
+    const g = offers.map(x => x[1]);
+    const search = (x: number) => {
+        let l = 0;
+        let r = n;
+        while (l < r) {
+            const mid = (l + r) >> 1;
+            if (g[mid] >= x) {
+                r = mid;
+            } else {
+                l = mid + 1;
+            }
+        }
+        return l;
+    };
+    for (let i = 1; i <= n; ++i) {
+        const j = search(offers[i - 1][0]);
+        f[i] = Math.max(f[i - 1], f[j] + offers[i - 1][2]);
+    }
+    return f[n];
+}
+```
+
+### **...**
+
+```
+
+```
+
+<!-- tabs:end -->
diff --git a/solution/2800-2899/2830.Maximize the Profit as the Salesman/README_EN.md b/solution/2800-2899/2830.Maximize the Profit as the Salesman/README_EN.md
new file mode 100644
index 0000000000000..0bb318b1112fb
--- /dev/null
+++ b/solution/2800-2899/2830.Maximize the Profit as the Salesman/README_EN.md	
@@ -0,0 +1,188 @@
+# [2830. Maximize the Profit as the Salesman](https://leetcode.com/problems/maximize-the-profit-as-the-salesman)
+
+[中文文档](/solution/2800-2899/2830.Maximize%20the%20Profit%20as%20the%20Salesman/README.md)
+
+## Description
+
+<p>You are given an integer <code>n</code> representing the number of houses on a number line, numbered from <code>0</code> to <code>n - 1</code>.</p>
+
+<p>Additionally, you are given a 2D integer array <code>offers</code> where <code>offers[i] = [start<sub>i</sub>, end<sub>i</sub>, gold<sub>i</sub>]</code>, indicating that <code>i<sup>th</sup></code> buyer wants to buy all the houses from <code>start<sub>i</sub></code> to <code>end<sub>i</sub></code> for <code>gold<sub>i</sub></code> amount of gold.</p>
+
+<p>As a salesman, your goal is to <strong>maximize</strong> your earnings by strategically selecting and selling houses to buyers.</p>
+
+<p>Return <em>the maximum amount of gold you can earn</em>.</p>
+
+<p><strong>Note</strong> that different buyers can&#39;t buy the same house, and some houses may remain unsold.</p>
+
+<p>&nbsp;</p>
+<p><strong class="example">Example 1:</strong></p>
+
+<pre>
+<strong>Input:</strong> n = 5, offers = [[0,0,1],[0,2,2],[1,3,2]]
+<strong>Output:</strong> 3
+<strong>Explanation:</strong> There are 5 houses numbered from 0 to 4 and there are 3 purchase offers.
+We sell houses in the range [0,0] to 1<sup>st</sup> buyer for 1 gold and houses in the range [1,3] to 3<sup>rd</sup> buyer for 2 golds.
+It can be proven that 3 is the maximum amount of gold we can achieve.
+</pre>
+
+<p><strong class="example">Example 2:</strong></p>
+
+<pre>
+<strong>Input:</strong> n = 5, offers = [[0,0,1],[0,2,10],[1,3,2]]
+<strong>Output:</strong> 10
+<strong>Explanation:</strong> There are 5 houses numbered from 0 to 4 and there are 3 purchase offers.
+We sell houses in the range [0,2] to 2<sup>nd</sup> buyer for 10 golds.
+It can be proven that 10 is the maximum amount of gold we can achieve.
+</pre>
+
+<p>&nbsp;</p>
+<p><strong>Constraints:</strong></p>
+
+<ul>
+	<li><code>1 &lt;= n &lt;= 10<sup>5</sup></code></li>
+	<li><code>1 &lt;= offers.length &lt;= 10<sup>5</sup></code></li>
+	<li><code>offers[i].length == 3</code></li>
+	<li><code>0 &lt;= start<sub>i</sub> &lt;= end<sub>i</sub> &lt;= n - 1</code></li>
+	<li><code>1 &lt;= gold<sub>i</sub> &lt;= 10<sup>3</sup></code></li>
+</ul>
+
+## Solutions
+
+<!-- tabs:start -->
+
+### **Python3**
+
+```python
+class Solution:
+    def maximizeTheProfit(self, n: int, offers: List[List[int]]) -> int:
+        offers.sort(key=lambda x: x[1])
+        f = [0] * (len(offers) + 1)
+        g = [x[1] for x in offers]
+        for i, (s, _, v) in enumerate(offers, 1):
+            j = bisect_left(g, s)
+            f[i] = max(f[i - 1], f[j] + v)
+        return f[-1]
+```
+
+### **Java**
+
+```java
+class Solution {
+    public int maximizeTheProfit(int n, List<List<Integer>> offers) {
+        offers.sort((a, b) -> a.get(1) - b.get(1));
+        n = offers.size();
+        int[] f = new int[n + 1];
+        int[] g = new int[n];
+        for (int i = 0; i < n; ++i) {
+            g[i] = offers.get(i).get(1);
+        }
+        for (int i = 1; i <= n; ++i) {
+            var o = offers.get(i - 1);
+            int j = search(g, o.get(0));
+            f[i] = Math.max(f[i - 1], f[j] + o.get(2));
+        }
+        return f[n];
+    }
+
+    private int search(int[] nums, int x) {
+        int l = 0, r = nums.length;
+        while (l < r) {
+            int mid = (l + r) >> 1;
+            if (nums[mid] >= x) {
+                r = mid;
+            } else {
+                l = mid + 1;
+            }
+        }
+        return l;
+    }
+}
+```
+
+### **C++**
+
+```cpp
+class Solution {
+public:
+    int maximizeTheProfit(int n, vector<vector<int>>& offers) {
+        sort(offers.begin(), offers.end(), [](const vector<int>& a, const vector<int>& b) {
+            return a[1] < b[1];
+        });
+        n = offers.size();
+        vector<int> f(n + 1);
+        vector<int> g;
+        for (auto& o : offers) {
+            g.push_back(o[1]);
+        }
+        for (int i = 1; i <= n; ++i) {
+            auto o = offers[i - 1];
+            int j = lower_bound(g.begin(), g.end(), o[0]) - g.begin();
+            f[i] = max(f[i - 1], f[j] + o[2]);
+        }
+        return f[n];
+    }
+};
+```
+
+### **Go**
+
+```go
+func maximizeTheProfit(n int, offers [][]int) int {
+	sort.Slice(offers, func(i, j int) bool { return offers[i][1] < offers[j][1] })
+	n = len(offers)
+	f := make([]int, n+1)
+	g := []int{}
+	for _, o := range offers {
+		g = append(g, o[1])
+	}
+	for i := 1; i <= n; i++ {
+		j := sort.SearchInts(g, offers[i-1][0])
+		f[i] = max(f[i-1], f[j]+offers[i-1][2])
+	}
+	return f[n]
+}
+
+func max(a, b int) int {
+	if a > b {
+		return a
+	}
+	return b
+}
+```
+
+### **TypeScript**
+
+```ts
+function maximizeTheProfit(n: number, offers: number[][]): number {
+    offers.sort((a, b) => a[1] - b[1]);
+    n = offers.length;
+    const f: number[] = Array(n + 1).fill(0);
+    const g = offers.map(x => x[1]);
+    const search = (x: number) => {
+        let l = 0;
+        let r = n;
+        while (l < r) {
+            const mid = (l + r) >> 1;
+            if (g[mid] >= x) {
+                r = mid;
+            } else {
+                l = mid + 1;
+            }
+        }
+        return l;
+    };
+    for (let i = 1; i <= n; ++i) {
+        const j = search(offers[i - 1][0]);
+        f[i] = Math.max(f[i - 1], f[j] + offers[i - 1][2]);
+    }
+    return f[n];
+}
+```
+
+### **...**
+
+```
+
+```
+
+<!-- tabs:end -->
diff --git a/solution/2800-2899/2830.Maximize the Profit as the Salesman/Solution.cpp b/solution/2800-2899/2830.Maximize the Profit as the Salesman/Solution.cpp
new file mode 100644
index 0000000000000..56432462a47b4
--- /dev/null
+++ b/solution/2800-2899/2830.Maximize the Profit as the Salesman/Solution.cpp	
@@ -0,0 +1,20 @@
+class Solution {
+public:
+    int maximizeTheProfit(int n, vector<vector<int>>& offers) {
+        sort(offers.begin(), offers.end(), [](const vector<int>& a, const vector<int>& b) {
+            return a[1] < b[1];
+        });
+        n = offers.size();
+        vector<int> f(n + 1);
+        vector<int> g;
+        for (auto& o : offers) {
+            g.push_back(o[1]);
+        }
+        for (int i = 1; i <= n; ++i) {
+            auto o = offers[i - 1];
+            int j = lower_bound(g.begin(), g.end(), o[0]) - g.begin();
+            f[i] = max(f[i - 1], f[j] + o[2]);
+        }
+        return f[n];
+    }
+};
\ No newline at end of file
diff --git a/solution/2800-2899/2830.Maximize the Profit as the Salesman/Solution.go b/solution/2800-2899/2830.Maximize the Profit as the Salesman/Solution.go
new file mode 100644
index 0000000000000..8fb8dbd90a28c
--- /dev/null
+++ b/solution/2800-2899/2830.Maximize the Profit as the Salesman/Solution.go	
@@ -0,0 +1,21 @@
+func maximizeTheProfit(n int, offers [][]int) int {
+	sort.Slice(offers, func(i, j int) bool { return offers[i][1] < offers[j][1] })
+	n = len(offers)
+	f := make([]int, n+1)
+	g := []int{}
+	for _, o := range offers {
+		g = append(g, o[1])
+	}
+	for i := 1; i <= n; i++ {
+		j := sort.SearchInts(g, offers[i-1][0])
+		f[i] = max(f[i-1], f[j]+offers[i-1][2])
+	}
+	return f[n]
+}
+
+func max(a, b int) int {
+	if a > b {
+		return a
+	}
+	return b
+}
\ No newline at end of file
diff --git a/solution/2800-2899/2830.Maximize the Profit as the Salesman/Solution.java b/solution/2800-2899/2830.Maximize the Profit as the Salesman/Solution.java
new file mode 100644
index 0000000000000..5826122dce9ea
--- /dev/null
+++ b/solution/2800-2899/2830.Maximize the Profit as the Salesman/Solution.java	
@@ -0,0 +1,30 @@
+class Solution {
+    public int maximizeTheProfit(int n, List<List<Integer>> offers) {
+        offers.sort((a, b) -> a.get(1) - b.get(1));
+        n = offers.size();
+        int[] f = new int[n + 1];
+        int[] g = new int[n];
+        for (int i = 0; i < n; ++i) {
+            g[i] = offers.get(i).get(1);
+        }
+        for (int i = 1; i <= n; ++i) {
+            var o = offers.get(i - 1);
+            int j = search(g, o.get(0));
+            f[i] = Math.max(f[i - 1], f[j] + o.get(2));
+        }
+        return f[n];
+    }
+
+    private int search(int[] nums, int x) {
+        int l = 0, r = nums.length;
+        while (l < r) {
+            int mid = (l + r) >> 1;
+            if (nums[mid] >= x) {
+                r = mid;
+            } else {
+                l = mid + 1;
+            }
+        }
+        return l;
+    }
+}
\ No newline at end of file
diff --git a/solution/2800-2899/2830.Maximize the Profit as the Salesman/Solution.py b/solution/2800-2899/2830.Maximize the Profit as the Salesman/Solution.py
new file mode 100644
index 0000000000000..6f7eeb04aaa58
--- /dev/null
+++ b/solution/2800-2899/2830.Maximize the Profit as the Salesman/Solution.py	
@@ -0,0 +1,9 @@
+class Solution:
+    def maximizeTheProfit(self, n: int, offers: List[List[int]]) -> int:
+        offers.sort(key=lambda x: x[1])
+        f = [0] * (len(offers) + 1)
+        g = [x[1] for x in offers]
+        for i, (s, _, v) in enumerate(offers, 1):
+            j = bisect_left(g, s)
+            f[i] = max(f[i - 1], f[j] + v)
+        return f[-1]
diff --git a/solution/2800-2899/2830.Maximize the Profit as the Salesman/Solution.ts b/solution/2800-2899/2830.Maximize the Profit as the Salesman/Solution.ts
new file mode 100644
index 0000000000000..53601c6dd7de7
--- /dev/null
+++ b/solution/2800-2899/2830.Maximize the Profit as the Salesman/Solution.ts	
@@ -0,0 +1,24 @@
+function maximizeTheProfit(n: number, offers: number[][]): number {
+    offers.sort((a, b) => a[1] - b[1]);
+    n = offers.length;
+    const f: number[] = Array(n + 1).fill(0);
+    const g = offers.map(x => x[1]);
+    const search = (x: number) => {
+        let l = 0;
+        let r = n;
+        while (l < r) {
+            const mid = (l + r) >> 1;
+            if (g[mid] >= x) {
+                r = mid;
+            } else {
+                l = mid + 1;
+            }
+        }
+        return l;
+    };
+    for (let i = 1; i <= n; ++i) {
+        const j = search(offers[i - 1][0]);
+        f[i] = Math.max(f[i - 1], f[j] + offers[i - 1][2]);
+    }
+    return f[n];
+}
diff --git a/solution/2800-2899/2831.Find the Longest Equal Subarray/README.md b/solution/2800-2899/2831.Find the Longest Equal Subarray/README.md
new file mode 100644
index 0000000000000..eff9106ec3698
--- /dev/null
+++ b/solution/2800-2899/2831.Find the Longest Equal Subarray/README.md	
@@ -0,0 +1,178 @@
+# [2831. 找出最长等值子数组](https://leetcode.cn/problems/find-the-longest-equal-subarray)
+
+[English Version](/solution/2800-2899/2831.Find%20the%20Longest%20Equal%20Subarray/README_EN.md)
+
+## 题目描述
+
+<!-- 这里写题目描述 -->
+
+<p>给你一个下标从 <strong>0</strong> 开始的整数数组 <code>nums</code> 和一个整数 <code>k</code> 。</p>
+
+<p>如果子数组中所有元素都相等,则认为子数组是一个 <strong>等值子数组</strong> 。注意,空数组是 <strong>等值子数组</strong> 。</p>
+
+<p>从 <code>nums</code> 中删除最多 <code>k</code> 个元素后,返回可能的最长等值子数组的长度。</p>
+
+<p><strong>子数组</strong> 是数组中一个连续且可能为空的元素序列。</p>
+
+<p>&nbsp;</p>
+
+<p><strong class="example">示例 1:</strong></p>
+
+<pre>
+<strong>输入:</strong>nums = [1,3,2,3,1,3], k = 3
+<strong>输出:</strong>3
+<strong>解释:</strong>最优的方案是删除下标 2 和下标 4 的元素。
+删除后,nums 等于 [1, 3, 3, 3] 。
+最长等值子数组从 i = 1 开始到 j = 3 结束,长度等于 3 。
+可以证明无法创建更长的等值子数组。
+</pre>
+
+<p><strong class="example">示例 2:</strong></p>
+
+<pre>
+<strong>输入:</strong>nums = [1,1,2,2,1,1], k = 2
+<strong>输出:</strong>4
+<strong>解释:</strong>最优的方案是删除下标 2 和下标 3 的元素。 
+删除后,nums 等于 [1, 1, 1, 1] 。 
+数组自身就是等值子数组,长度等于 4 。 
+可以证明无法创建更长的等值子数组。
+</pre>
+
+<p>&nbsp;</p>
+
+<p><strong>提示:</strong></p>
+
+<ul>
+	<li><code>1 &lt;= nums.length &lt;= 10<sup>5</sup></code></li>
+	<li><code>1 &lt;= nums[i] &lt;= nums.length</code></li>
+	<li><code>0 &lt;= k &lt;= nums.length</code></li>
+</ul>
+
+## 解法
+
+<!-- 这里可写通用的实现逻辑 -->
+
+**方法一:哈希表 + 双指针**
+
+我们用双指针维护一个单调变长的窗口,用哈希表维护窗口中每个元素出现的次数。
+
+窗口中的所有元素个数减去窗口中出现次数最多的元素个数,就是窗口中需要删除的元素个数。
+
+每一次,我们将右指针指向的元素加入窗口,然后更新哈希表,同时更新窗口中出现次数最多的元素个数。当窗口中需要删除的元素个数超过了 $k$ 时,我们就移动一次左指针,然后更新哈希表。
+
+遍历结束后,返回出现次数最多的元素个数即可。
+
+时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组的长度。
+
+<!-- tabs:start -->
+
+### **Python3**
+
+<!-- 这里可写当前语言的特殊实现逻辑 -->
+
+```python
+class Solution:
+    def longestEqualSubarray(self, nums: List[int], k: int) -> int:
+        cnt = Counter()
+        l = 0
+        mx = 0
+        for r, x in enumerate(nums):
+            cnt[x] += 1
+            mx = max(mx, cnt[x])
+            if r - l + 1 - mx > k:
+                cnt[nums[l]] -= 1
+                l += 1
+        return mx
+```
+
+### **Java**
+
+<!-- 这里可写当前语言的特殊实现逻辑 -->
+
+```java
+class Solution {
+    public int longestEqualSubarray(List<Integer> nums, int k) {
+        Map<Integer, Integer> cnt = new HashMap<>();
+        int mx = 0, l = 0;
+        for (int r = 0; r < nums.size(); ++r) {
+            cnt.merge(nums.get(r), 1, Integer::sum);
+            mx = Math.max(mx, cnt.get(nums.get(r)));
+            if (r - l + 1 - mx > k) {
+                cnt.merge(nums.get(l++), -1, Integer::sum);
+            }
+        }
+        return mx;
+    }
+}
+```
+
+### **C++**
+
+```cpp
+class Solution {
+public:
+    int longestEqualSubarray(vector<int>& nums, int k) {
+        unordered_map<int, int> cnt;
+        int mx = 0, l = 0;
+        for (int r = 0; r < nums.size(); ++r) {
+            mx = max(mx, ++cnt[nums[r]]);
+            if (r - l + 1 - mx > k) {
+                --cnt[nums[l++]];
+            }
+        }
+        return mx;
+    }
+};
+```
+
+### **Go**
+
+```go
+func longestEqualSubarray(nums []int, k int) int {
+	cnt := map[int]int{}
+	mx, l := 0, 0
+	for r, x := range nums {
+		cnt[x]++
+		mx = max(mx, cnt[x])
+		if r-l+1-mx > k {
+			cnt[nums[l]]--
+			l++
+		}
+	}
+	return mx
+}
+
+func max(a, b int) int {
+	if a > b {
+		return a
+	}
+	return b
+}
+```
+
+### **TypeScript**
+
+```ts
+function longestEqualSubarray(nums: number[], k: number): number {
+    const cnt: Map<number, number> = new Map();
+    let mx = 0;
+    let l = 0;
+    for (let r = 0; r < nums.length; ++r) {
+        cnt.set(nums[r], (cnt.get(nums[r]) ?? 0) + 1);
+        mx = Math.max(mx, cnt.get(nums[r])!);
+        if (r - l + 1 - mx > k) {
+            cnt.set(nums[l], cnt.get(nums[l])! - 1);
+            ++l;
+        }
+    }
+    return mx;
+}
+```
+
+### **...**
+
+```
+
+```
+
+<!-- tabs:end -->
diff --git a/solution/2800-2899/2831.Find the Longest Equal Subarray/README_EN.md b/solution/2800-2899/2831.Find the Longest Equal Subarray/README_EN.md
new file mode 100644
index 0000000000000..8b56b55842359
--- /dev/null
+++ b/solution/2800-2899/2831.Find the Longest Equal Subarray/README_EN.md	
@@ -0,0 +1,156 @@
+# [2831. Find the Longest Equal Subarray](https://leetcode.com/problems/find-the-longest-equal-subarray)
+
+[中文文档](/solution/2800-2899/2831.Find%20the%20Longest%20Equal%20Subarray/README.md)
+
+## Description
+
+<p>You are given a <strong>0-indexed</strong> integer array <code>nums</code> and an integer <code>k</code>.</p>
+
+<p>A subarray is called <strong>equal</strong> if all of its elements are equal. Note that the empty subarray is an <strong>equal</strong> subarray.</p>
+
+<p>Return <em>the length of the <strong>longest</strong> possible equal subarray after deleting <strong>at most</strong> </em><code>k</code><em> elements from </em><code>nums</code>.</p>
+
+<p>A <b>subarray</b> is a contiguous, possibly empty sequence of elements within an array.</p>
+
+<p>&nbsp;</p>
+<p><strong class="example">Example 1:</strong></p>
+
+<pre>
+<strong>Input:</strong> nums = [1,3,2,3,1,3], k = 3
+<strong>Output:</strong> 3
+<strong>Explanation:</strong> It&#39;s optimal to delete the elements at index 2 and index 4.
+After deleting them, nums becomes equal to [1, 3, 3, 3].
+The longest equal subarray starts at i = 1 and ends at j = 3 with length equal to 3.
+It can be proven that no longer equal subarrays can be created.
+</pre>
+
+<p><strong class="example">Example 2:</strong></p>
+
+<pre>
+<strong>Input:</strong> nums = [1,1,2,2,1,1], k = 2
+<strong>Output:</strong> 4
+<strong>Explanation:</strong> It&#39;s optimal to delete the elements at index 2 and index 3.
+After deleting them, nums becomes equal to [1, 1, 1, 1].
+The array itself is an equal subarray, so the answer is 4.
+It can be proven that no longer equal subarrays can be created.
+</pre>
+
+<p>&nbsp;</p>
+<p><strong>Constraints:</strong></p>
+
+<ul>
+	<li><code>1 &lt;= nums.length &lt;= 10<sup>5</sup></code></li>
+	<li><code>1 &lt;= nums[i] &lt;= nums.length</code></li>
+	<li><code>0 &lt;= k &lt;= nums.length</code></li>
+</ul>
+
+## Solutions
+
+<!-- tabs:start -->
+
+### **Python3**
+
+```python
+class Solution:
+    def longestEqualSubarray(self, nums: List[int], k: int) -> int:
+        cnt = Counter()
+        l = 0
+        mx = 0
+        for r, x in enumerate(nums):
+            cnt[x] += 1
+            mx = max(mx, cnt[x])
+            if r - l + 1 - mx > k:
+                cnt[nums[l]] -= 1
+                l += 1
+        return mx
+```
+
+### **Java**
+
+```java
+class Solution {
+    public int longestEqualSubarray(List<Integer> nums, int k) {
+        Map<Integer, Integer> cnt = new HashMap<>();
+        int mx = 0, l = 0;
+        for (int r = 0; r < nums.size(); ++r) {
+            cnt.merge(nums.get(r), 1, Integer::sum);
+            mx = Math.max(mx, cnt.get(nums.get(r)));
+            if (r - l + 1 - mx > k) {
+                cnt.merge(nums.get(l++), -1, Integer::sum);
+            }
+        }
+        return mx;
+    }
+}
+```
+
+### **C++**
+
+```cpp
+class Solution {
+public:
+    int longestEqualSubarray(vector<int>& nums, int k) {
+        unordered_map<int, int> cnt;
+        int mx = 0, l = 0;
+        for (int r = 0; r < nums.size(); ++r) {
+            mx = max(mx, ++cnt[nums[r]]);
+            if (r - l + 1 - mx > k) {
+                --cnt[nums[l++]];
+            }
+        }
+        return mx;
+    }
+};
+```
+
+### **Go**
+
+```go
+func longestEqualSubarray(nums []int, k int) int {
+	cnt := map[int]int{}
+	mx, l := 0, 0
+	for r, x := range nums {
+		cnt[x]++
+		mx = max(mx, cnt[x])
+		if r-l+1-mx > k {
+			cnt[nums[l]]--
+			l++
+		}
+	}
+	return mx
+}
+
+func max(a, b int) int {
+	if a > b {
+		return a
+	}
+	return b
+}
+```
+
+### **TypeScript**
+
+```ts
+function longestEqualSubarray(nums: number[], k: number): number {
+    const cnt: Map<number, number> = new Map();
+    let mx = 0;
+    let l = 0;
+    for (let r = 0; r < nums.length; ++r) {
+        cnt.set(nums[r], (cnt.get(nums[r]) ?? 0) + 1);
+        mx = Math.max(mx, cnt.get(nums[r])!);
+        if (r - l + 1 - mx > k) {
+            cnt.set(nums[l], cnt.get(nums[l])! - 1);
+            ++l;
+        }
+    }
+    return mx;
+}
+```
+
+### **...**
+
+```
+
+```
+
+<!-- tabs:end -->
diff --git a/solution/2800-2899/2831.Find the Longest Equal Subarray/Solution.cpp b/solution/2800-2899/2831.Find the Longest Equal Subarray/Solution.cpp
new file mode 100644
index 0000000000000..18272fa904d0f
--- /dev/null
+++ b/solution/2800-2899/2831.Find the Longest Equal Subarray/Solution.cpp	
@@ -0,0 +1,14 @@
+class Solution {
+public:
+    int longestEqualSubarray(vector<int>& nums, int k) {
+        unordered_map<int, int> cnt;
+        int mx = 0, l = 0;
+        for (int r = 0; r < nums.size(); ++r) {
+            mx = max(mx, ++cnt[nums[r]]);
+            if (r - l + 1 - mx > k) {
+                --cnt[nums[l++]];
+            }
+        }
+        return mx;
+    }
+};
\ No newline at end of file
diff --git a/solution/2800-2899/2831.Find the Longest Equal Subarray/Solution.go b/solution/2800-2899/2831.Find the Longest Equal Subarray/Solution.go
new file mode 100644
index 0000000000000..a9c74f51465fe
--- /dev/null
+++ b/solution/2800-2899/2831.Find the Longest Equal Subarray/Solution.go	
@@ -0,0 +1,20 @@
+func longestEqualSubarray(nums []int, k int) int {
+	cnt := map[int]int{}
+	mx, l := 0, 0
+	for r, x := range nums {
+		cnt[x]++
+		mx = max(mx, cnt[x])
+		if r-l+1-mx > k {
+			cnt[nums[l]]--
+			l++
+		}
+	}
+	return mx
+}
+
+func max(a, b int) int {
+	if a > b {
+		return a
+	}
+	return b
+}
\ No newline at end of file
diff --git a/solution/2800-2899/2831.Find the Longest Equal Subarray/Solution.java b/solution/2800-2899/2831.Find the Longest Equal Subarray/Solution.java
new file mode 100644
index 0000000000000..e222a18aafc5d
--- /dev/null
+++ b/solution/2800-2899/2831.Find the Longest Equal Subarray/Solution.java	
@@ -0,0 +1,14 @@
+class Solution {
+    public int longestEqualSubarray(List<Integer> nums, int k) {
+        Map<Integer, Integer> cnt = new HashMap<>();
+        int mx = 0, l = 0;
+        for (int r = 0; r < nums.size(); ++r) {
+            cnt.merge(nums.get(r), 1, Integer::sum);
+            mx = Math.max(mx, cnt.get(nums.get(r)));
+            if (r - l + 1 - mx > k) {
+                cnt.merge(nums.get(l++), -1, Integer::sum);
+            }
+        }
+        return mx;
+    }
+}
\ No newline at end of file
diff --git a/solution/2800-2899/2831.Find the Longest Equal Subarray/Solution.py b/solution/2800-2899/2831.Find the Longest Equal Subarray/Solution.py
new file mode 100644
index 0000000000000..47a7b6013d0e6
--- /dev/null
+++ b/solution/2800-2899/2831.Find the Longest Equal Subarray/Solution.py	
@@ -0,0 +1,12 @@
+class Solution:
+    def longestEqualSubarray(self, nums: List[int], k: int) -> int:
+        cnt = Counter()
+        l = 0
+        mx = 0
+        for r, x in enumerate(nums):
+            cnt[x] += 1
+            mx = max(mx, cnt[x])
+            if r - l + 1 - mx > k:
+                cnt[nums[l]] -= 1
+                l += 1
+        return mx
diff --git a/solution/2800-2899/2831.Find the Longest Equal Subarray/Solution.ts b/solution/2800-2899/2831.Find the Longest Equal Subarray/Solution.ts
new file mode 100644
index 0000000000000..cb58a697d8c45
--- /dev/null
+++ b/solution/2800-2899/2831.Find the Longest Equal Subarray/Solution.ts	
@@ -0,0 +1,14 @@
+function longestEqualSubarray(nums: number[], k: number): number {
+    const cnt: Map<number, number> = new Map();
+    let mx = 0;
+    let l = 0;
+    for (let r = 0; r < nums.length; ++r) {
+        cnt.set(nums[r], (cnt.get(nums[r]) ?? 0) + 1);
+        mx = Math.max(mx, cnt.get(nums[r])!);
+        if (r - l + 1 - mx > k) {
+            cnt.set(nums[l], cnt.get(nums[l])! - 1);
+            ++l;
+        }
+    }
+    return mx;
+}
diff --git a/solution/CONTEST_README.md b/solution/CONTEST_README.md
index b7fc38cdde040..52906c21d5dc9 100644
--- a/solution/CONTEST_README.md
+++ b/solution/CONTEST_README.md
@@ -22,6 +22,20 @@
 
 ## 往期竞赛
 
+#### 第 359 场周赛(2023-08-20 10:30, 90 分钟) 参赛人数 4097
+
+- [2828. 判别首字母缩略词](/solution/2800-2899/2828.Check%20if%20a%20String%20Is%20an%20Acronym%20of%20Words/README.md)
+- [2829. k-avoiding 数组的最小总和](/solution/2800-2899/2829.Determine%20the%20Minimum%20Sum%20of%20a%20k-avoiding%20Array/README.md)
+- [2830. 销售利润最大化](/solution/2800-2899/2830.Maximize%20the%20Profit%20as%20the%20Salesman/README.md)
+- [2831. 找出最长等值子数组](/solution/2800-2899/2831.Find%20the%20Longest%20Equal%20Subarray/README.md)
+
+#### 第 111 场双周赛(2023-08-19 22:30, 90 分钟) 参赛人数 2787
+
+- [2824. 统计和小于目标的下标对数目](/solution/2800-2899/2824.Count%20Pairs%20Whose%20Sum%20is%20Less%20than%20Target/README.md)
+- [2825. 循环增长使字符串子序列等于另一个字符串](/solution/2800-2899/2825.Make%20String%20a%20Subsequence%20Using%20Cyclic%20Increments/README.md)
+- [2826. 将三个组排序](/solution/2800-2899/2826.Sorting%20Three%20Groups/README.md)
+- [2827. 范围中美丽整数的数目](/solution/2800-2899/2827.Number%20of%20Beautiful%20Integers%20in%20the%20Range/README.md)
+
 #### 第 358 场周赛(2023-08-13 10:30, 90 分钟) 参赛人数 4475
 
 - [2815. 数组中的最大数对和](/solution/2800-2899/2815.Max%20Pair%20Sum%20in%20an%20Array/README.md)
diff --git a/solution/CONTEST_README_EN.md b/solution/CONTEST_README_EN.md
index e43e47bff61a0..62bca35de9ba2 100644
--- a/solution/CONTEST_README_EN.md
+++ b/solution/CONTEST_README_EN.md
@@ -25,6 +25,20 @@ Get your rating changes right after the completion of LeetCode contests, https:/
 
 ## Past Contests
 
+#### Weekly Contest 359
+
+- [2828. Check if a String Is an Acronym of Words](/solution/2800-2899/2828.Check%20if%20a%20String%20Is%20an%20Acronym%20of%20Words/README_EN.md)
+- [2829. Determine the Minimum Sum of a k-avoiding Array](/solution/2800-2899/2829.Determine%20the%20Minimum%20Sum%20of%20a%20k-avoiding%20Array/README_EN.md)
+- [2830. Maximize the Profit as the Salesman](/solution/2800-2899/2830.Maximize%20the%20Profit%20as%20the%20Salesman/README_EN.md)
+- [2831. Find the Longest Equal Subarray](/solution/2800-2899/2831.Find%20the%20Longest%20Equal%20Subarray/README_EN.md)
+
+#### Biweekly Contest 111
+
+- [2824. Count Pairs Whose Sum is Less than Target](/solution/2800-2899/2824.Count%20Pairs%20Whose%20Sum%20is%20Less%20than%20Target/README_EN.md)
+- [2825. Make String a Subsequence Using Cyclic Increments](/solution/2800-2899/2825.Make%20String%20a%20Subsequence%20Using%20Cyclic%20Increments/README_EN.md)
+- [2826. Sorting Three Groups](/solution/2800-2899/2826.Sorting%20Three%20Groups/README_EN.md)
+- [2827. Number of Beautiful Integers in the Range](/solution/2800-2899/2827.Number%20of%20Beautiful%20Integers%20in%20the%20Range/README_EN.md)
+
 #### Weekly Contest 358
 
 - [2815. Max Pair Sum in an Array](/solution/2800-2899/2815.Max%20Pair%20Sum%20in%20an%20Array/README_EN.md)
diff --git a/solution/README.md b/solution/README.md
index 9971f5ca016c5..c05510b08b492 100644
--- a/solution/README.md
+++ b/solution/README.md
@@ -2834,6 +2834,14 @@
 |  2821  |  [延迟每个 Promise 对象的解析](/solution/2800-2899/2821.Delay%20the%20Resolution%20of%20Each%20Promise/README.md)  |    |  简单  |  🔒  |
 |  2822  |  [对象反转](/solution/2800-2899/2822.Inversion%20of%20Object/README.md)  |    |  简单  |  🔒  |
 |  2823  |  [深度对象筛选](/solution/2800-2899/2823.Deep%20Object%20Filter/README.md)  |    |  中等  |  🔒  |
+|  2824  |  [统计和小于目标的下标对数目](/solution/2800-2899/2824.Count%20Pairs%20Whose%20Sum%20is%20Less%20than%20Target/README.md)  |    |  简单  |  第 111 场双周赛  |
+|  2825  |  [循环增长使字符串子序列等于另一个字符串](/solution/2800-2899/2825.Make%20String%20a%20Subsequence%20Using%20Cyclic%20Increments/README.md)  |    |  中等  |  第 111 场双周赛  |
+|  2826  |  [将三个组排序](/solution/2800-2899/2826.Sorting%20Three%20Groups/README.md)  |    |  中等  |  第 111 场双周赛  |
+|  2827  |  [范围中美丽整数的数目](/solution/2800-2899/2827.Number%20of%20Beautiful%20Integers%20in%20the%20Range/README.md)  |    |  困难  |  第 111 场双周赛  |
+|  2828  |  [判别首字母缩略词](/solution/2800-2899/2828.Check%20if%20a%20String%20Is%20an%20Acronym%20of%20Words/README.md)  |    |  简单  |  第 359 场周赛  |
+|  2829  |  [k-avoiding 数组的最小总和](/solution/2800-2899/2829.Determine%20the%20Minimum%20Sum%20of%20a%20k-avoiding%20Array/README.md)  |    |  中等  |  第 359 场周赛  |
+|  2830  |  [销售利润最大化](/solution/2800-2899/2830.Maximize%20the%20Profit%20as%20the%20Salesman/README.md)  |    |  中等  |  第 359 场周赛  |
+|  2831  |  [找出最长等值子数组](/solution/2800-2899/2831.Find%20the%20Longest%20Equal%20Subarray/README.md)  |    |  中等  |  第 359 场周赛  |
 
 ## 版权
 
diff --git a/solution/README_EN.md b/solution/README_EN.md
index 8af80d2f21c46..753e85c734714 100644
--- a/solution/README_EN.md
+++ b/solution/README_EN.md
@@ -2832,6 +2832,14 @@ Press <kbd>Control</kbd>+<kbd>F</kbd>(or <kbd>Command</kbd>+<kbd>F</kbd> on the
 |  2821  |  [Delay the Resolution of Each Promise](/solution/2800-2899/2821.Delay%20the%20Resolution%20of%20Each%20Promise/README_EN.md)  |    |  Easy  |  🔒  |
 |  2822  |  [Inversion of Object](/solution/2800-2899/2822.Inversion%20of%20Object/README_EN.md)  |    |  Easy  |  🔒  |
 |  2823  |  [Deep Object Filter](/solution/2800-2899/2823.Deep%20Object%20Filter/README_EN.md)  |    |  Medium  |  🔒  |
+|  2824  |  [Count Pairs Whose Sum is Less than Target](/solution/2800-2899/2824.Count%20Pairs%20Whose%20Sum%20is%20Less%20than%20Target/README_EN.md)  |    |  Easy  |  Biweekly Contest 111  |
+|  2825  |  [Make String a Subsequence Using Cyclic Increments](/solution/2800-2899/2825.Make%20String%20a%20Subsequence%20Using%20Cyclic%20Increments/README_EN.md)  |    |  Medium  |  Biweekly Contest 111  |
+|  2826  |  [Sorting Three Groups](/solution/2800-2899/2826.Sorting%20Three%20Groups/README_EN.md)  |    |  Medium  |  Biweekly Contest 111  |
+|  2827  |  [Number of Beautiful Integers in the Range](/solution/2800-2899/2827.Number%20of%20Beautiful%20Integers%20in%20the%20Range/README_EN.md)  |    |  Hard  |  Biweekly Contest 111  |
+|  2828  |  [Check if a String Is an Acronym of Words](/solution/2800-2899/2828.Check%20if%20a%20String%20Is%20an%20Acronym%20of%20Words/README_EN.md)  |    |  Easy  |  Weekly Contest 359  |
+|  2829  |  [Determine the Minimum Sum of a k-avoiding Array](/solution/2800-2899/2829.Determine%20the%20Minimum%20Sum%20of%20a%20k-avoiding%20Array/README_EN.md)  |    |  Medium  |  Weekly Contest 359  |
+|  2830  |  [Maximize the Profit as the Salesman](/solution/2800-2899/2830.Maximize%20the%20Profit%20as%20the%20Salesman/README_EN.md)  |    |  Medium  |  Weekly Contest 359  |
+|  2831  |  [Find the Longest Equal Subarray](/solution/2800-2899/2831.Find%20the%20Longest%20Equal%20Subarray/README_EN.md)  |    |  Medium  |  Weekly Contest 359  |
 
 ## Copyright
 
diff --git a/solution/summary.md b/solution/summary.md
index 6965bf4206e44..cbd37684d52a3 100644
--- a/solution/summary.md
+++ b/solution/summary.md
@@ -2879,3 +2879,11 @@
   - [2821.延迟每个 Promise 对象的解析](/solution/2800-2899/2821.Delay%20the%20Resolution%20of%20Each%20Promise/README.md)
   - [2822.对象反转](/solution/2800-2899/2822.Inversion%20of%20Object/README.md)
   - [2823.深度对象筛选](/solution/2800-2899/2823.Deep%20Object%20Filter/README.md)
+  - [2824.统计和小于目标的下标对数目](/solution/2800-2899/2824.Count%20Pairs%20Whose%20Sum%20is%20Less%20than%20Target/README.md)
+  - [2825.循环增长使字符串子序列等于另一个字符串](/solution/2800-2899/2825.Make%20String%20a%20Subsequence%20Using%20Cyclic%20Increments/README.md)
+  - [2826.将三个组排序](/solution/2800-2899/2826.Sorting%20Three%20Groups/README.md)
+  - [2827.范围中美丽整数的数目](/solution/2800-2899/2827.Number%20of%20Beautiful%20Integers%20in%20the%20Range/README.md)
+  - [2828.判别首字母缩略词](/solution/2800-2899/2828.Check%20if%20a%20String%20Is%20an%20Acronym%20of%20Words/README.md)
+  - [2829.k-avoiding 数组的最小总和](/solution/2800-2899/2829.Determine%20the%20Minimum%20Sum%20of%20a%20k-avoiding%20Array/README.md)
+  - [2830.销售利润最大化](/solution/2800-2899/2830.Maximize%20the%20Profit%20as%20the%20Salesman/README.md)
+  - [2831.找出最长等值子数组](/solution/2800-2899/2831.Find%20the%20Longest%20Equal%20Subarray/README.md)
diff --git a/solution/summary_en.md b/solution/summary_en.md
index 27fc4f74b1a68..a5010b0ffed77 100644
--- a/solution/summary_en.md
+++ b/solution/summary_en.md
@@ -2879,3 +2879,11 @@
   - [2821.Delay the Resolution of Each Promise](/solution/2800-2899/2821.Delay%20the%20Resolution%20of%20Each%20Promise/README_EN.md)
   - [2822.Inversion of Object](/solution/2800-2899/2822.Inversion%20of%20Object/README_EN.md)
   - [2823.Deep Object Filter](/solution/2800-2899/2823.Deep%20Object%20Filter/README_EN.md)
+  - [2824.Count Pairs Whose Sum is Less than Target](/solution/2800-2899/2824.Count%20Pairs%20Whose%20Sum%20is%20Less%20than%20Target/README_EN.md)
+  - [2825.Make String a Subsequence Using Cyclic Increments](/solution/2800-2899/2825.Make%20String%20a%20Subsequence%20Using%20Cyclic%20Increments/README_EN.md)
+  - [2826.Sorting Three Groups](/solution/2800-2899/2826.Sorting%20Three%20Groups/README_EN.md)
+  - [2827.Number of Beautiful Integers in the Range](/solution/2800-2899/2827.Number%20of%20Beautiful%20Integers%20in%20the%20Range/README_EN.md)
+  - [2828.Check if a String Is an Acronym of Words](/solution/2800-2899/2828.Check%20if%20a%20String%20Is%20an%20Acronym%20of%20Words/README_EN.md)
+  - [2829.Determine the Minimum Sum of a k-avoiding Array](/solution/2800-2899/2829.Determine%20the%20Minimum%20Sum%20of%20a%20k-avoiding%20Array/README_EN.md)
+  - [2830.Maximize the Profit as the Salesman](/solution/2800-2899/2830.Maximize%20the%20Profit%20as%20the%20Salesman/README_EN.md)
+  - [2831.Find the Longest Equal Subarray](/solution/2800-2899/2831.Find%20the%20Longest%20Equal%20Subarray/README_EN.md)