alg2025/src/2/P6476.md
2025-02-05 16:18:59 +08:00

191 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

为了解决这个问题我们需要判断是否存在一种涂色方案使得在忽略未染色格子后不存在k个连续的相同颜色的格子。通过分析我们可以利用数学方法来确定这种方案的存在性。
### 方法思路
1. **最大公约数 (GCD) 和最小公倍数 (LCM)**首先计算给定两个数p1和p2的GCD这有助于确定它们的倍数分布。
2. **非公共倍数数目**计算每个数的非公共倍数数目即那些仅属于p1或p2的倍数。
3. **最大连续块长度**:通过数学公式计算在忽略公共倍数的情况下,红色和蓝色格子的最大连续块长度。
4. **判断条件**:根据计算的最大连续块长度判断是否存在满足条件的涂色方案。
### 解决代码
```cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while (T--) {
long long p1, p2, k;
cin >> p1 >> p2 >> k;
if (k == 1) {
cout << "NO\n";
continue;
}
long long g = gcd(p1, p2);
long long R = (p2 / g) - 1;
long long B = (p1 / g) - 1;
if (R < 0) R = 0;
if (B < 0) B = 0;
long long max_red = (R + B) / (B + 1);
long long max_blue = (B + R) / (R + 1);
long long max_val = max(max_red, max_blue);
if (max_val >= k) {
cout << "NO\n";
} else {
cout << "YES\n";
}
}
return 0;
}
```
### 代码解释
1. **输入处理**:使用快速输入输出处理多组测试数据。
2. **特殊情况处理**当k为1时直接输出"NO",因为不可能存在不连续的涂色方案。
3. **GCD计算**计算p1和p2的最大公约数g。
4. **非公共倍数数目计算**计算每个数的非公共倍数数目R和B。
5. **最大连续块长度计算**:通过公式计算红色和蓝色的最大连续块长度。
6. **条件判断**根据最大连续块长度与k的比较输出结果。
该方法高效地利用了数学性质避免了直接遍历所有可能的涂色方案能够在O(1)时间内处理每个测试用例,适用于大规模输入。
你的代码旨在解决一个染色格子的组合问题,具体来说是判断是否存在一种染色方案,使得在染色后的格子中,不存在 $k$ 个连续相同颜色的格子。以下是对你的代码逻辑的详细解释:
## 问题回顾
你有编号从 $0$ 到 $10^{20}-1$ 的格子。初始时,所有格子都未染色。染色规则如下:
1. 编号是 $p_1$ 倍数的格子染成红色。
2. 编号是 $p_2$ 倍数的格子染成蓝色。
3. 如果一个格子编号是既是 $p_1$ 倍数又是 $p_2$ 倍数,可以选择染成红色或蓝色。
最终,需要判断是否存在一种染色方案,使得染色后的格子中不存在 $k$ 个连续相同颜色的格子。
## 代码逻辑分析
```cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) {
long long p1, p2, k;
cin >> p1 >> p2 >> k;
if (k == 1) {
cout << "NO\n";
continue;
}
long long g = gcd(p1, p2);
long long R = (p2 / g) - 1;
long long B = (p1 / g) - 1;
if (R < 0) R = 0;
if (B < 0) B = 0;
long long max_red = (R + B) / (B + 1);
long long max_blue = (B + R) / (R + 1);
long long max_val = max(max_red, max_blue);
if (max_val >= k) {
cout << "NO\n";
} else {
cout << "YES\n";
}
}
return 0;
}
```
### 1. 输入读取与预处理
- **输入多组数据:** 首先读取测试数据组数 $T$,然后对于每组数据,读取三个参数 $p_1, p_2, k$。
```cpp
int T;
cin >> T;
while (T--) {
long long p1, p2, k;
cin >> p1 >> p2 >> k;
// 处理逻辑
}
```
### 2. 特殊情况处理
- **当 $k = 1$** 如果 $k = 1$,意味着不允许有任何一个染色格子存在(因为任何一个染色都会违反),因此直接输出 `NO`
```cpp
if (k == 1) {
cout << "NO\n";
continue;
}
```
### 3. 计算公倍数和未染色格子
- **求最大公约数 $g$** 计算 $p_1$ 和 $p_2$ 的最大公约数 $g$。这有助于找到它们的最小公倍数。
```cpp
long long g = gcd(p1, p2);
```
- **计算交集格子的周期**
- **红色格子的周期:** 红色格子的周期为 $p_1$,蓝色格子的周期为 $p_2$。共有交集格子的周期为 $\text{lcm}(p_1, p_2) = \frac{p_1 \times p_2}{g}$。
- **计算红色和蓝色的最大连续数:**
```cpp
long long R = (p2 / g) - 1;
long long B = (p1 / g) - 1;
if (R < 0) R = 0;
if (B < 0) B = 0;
```
- 这里`R` `B` 分别代表在一个周期内红色和蓝色之间的最大连续未染色格子数具体来说
- `R = (p2 / g) - 1`在蓝色格子之间最多可以有 $(\frac{p_2}{g} - 1)$ 个未染色的红色格子
- `B = (p1 / g) - 1`在红色格子之间最多可以有 $(\frac{p_1}{g} - 1)$ 个未染色的蓝色格子
- 如果计算出的 `R` `B` 为负数 $p_2 < g$ $p_1 < g$则将其设为 $0$因为这意味着在这种情况下没有未染色的连续格子
### 4. 计算最大连续相同颜色的格子数
```cpp
long long max_red = (R + B) / (B + 1);
long long max_blue = (B + R) / (R + 1);
long long max_val = max(max_red, max_blue);
```
- **`max_red` `max_blue` 的含义**
- `max_red`在红色格子之间允许的最大连续红色格子数
- `max_blue`在蓝色格子之间允许的最大连续蓝色格子数
具体计算方式
- `(R + B) / (B + 1)`这是为了确保在分布 $R$ 个红色格子和 $B$ 个蓝色格子时红色格子的连续数不超过 $k-1$。类似地`(B + R) / (R + 1)` 确保蓝色格子的连续数不超过 $k-1$。
- **`max_val`** `max_red` `max_blue` 中的较大值代表在染色方案中可能的最大连续相同颜色格子数
### 5. 判断是否存在非无聊的染色方案
```cpp
if (max_val >= k) {
cout << "NO\n";
} else {
cout << "YES\n";
}
```
- **判断逻辑**
- 如果 `max_val >= k`意味着在某种情况下存在 $k$ 个连续相同颜色的格子这样的染色方案是无聊的因此输出 `NO`
- 否则存在一种染色方式可以避免 $k$ 个连续相同颜色的格子因此输出 `YES`
## 代码整体思路总结
1. **处理特殊情况:** 如果不允许有任何一个染色格子 $k = 1$),直接输出 `NO`
2. **计算周期与交集:** 通过计算 $p_1$ $p_2$ 的最大公约数确定红色和蓝色格子相互之间的分布周期
3. **计算允许的最大连续颜色数:** 通过分析红色和蓝色格子之间的未染色间隔计算在染色过程中可能出现的最大连续相同颜色的格子数
4. **判断染色方案的可行性:** 比较计算出的最大连续颜色数是否达到或超过禁忌值 $k$从而决定是否存在一种不无聊的染色方案
这种方法通过数学推导和周期性分析避免了对 $10^{20}$ 个格子的逐一检查极大地提高了效率适用于大规模数据的处理