把 a2 约去 a1 和后续所有数能提供的质因子,剩余分母为 1 时存在整数括号方案。
OJ: luogu
题目 ID: P2651
难度:普及+/提高
标签:最大公约数分数思维python
日期: 2026-07-16 19:20
题意
给出连续除法 a1/a2/.../an,可以任意添加括号,问能否使结果成为整数。
思路
通过括号 a1/(a2/a3/a4/...),a3..an 都有机会进入总分子。因此可行的充要条件是:a2 的全部质因子幂能由 a1*a3*...*an 约掉。
不直接计算巨大乘积。先令:
text
denominator=a2/gcd(a1,a2)再依次用每个后续数与当前分母的 gcd 约分。最后分母等于 1 则输出 Yes。
Python 知识
math.gcd让约分直接作用于剩余分母。- 列表切片取得每组表达式,读取指针处理变长测试用例。
- 逐步约分避免构造可能极大的乘积,虽然 Python 支持大整数,也应控制不必要运算。
- 条件表达式生成
Yes/No。 /home/rainboy/mycode/hugo-blog/content/program_language/python/cpp_to_python_pitfalls.md:大整数不代表应忽略算法规模。/home/rainboy/mycode/hugo-blog/content/program_language/python/oj_input_output_cheatsheet.md:变长多组输入。
代码
python
import sys
from math import gcd
def main():
data = list(map(int, sys.stdin.buffer.read().split()))
test_count = data[0]
pos = 1
answer = []
for _ in range(test_count):
n = data[pos]
numbers = data[pos + 1:pos + n + 1]
pos += n + 1
denominator = numbers[1] // gcd(numbers[0], numbers[1])
for factor in numbers[2:]:
denominator //= gcd(denominator, factor)
answer.append("Yes" if denominator == 1 else "No")
print("\n".join(answer))
if __name__ == "__main__":
main()cpp
/**
* P2651 添加括号III
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-07-27 00:00
* update_at: 2026-07-27 00:00
*/
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
scanf("%d", &t);
while (t--) {
int n;
scanf("%d", &n);
int a[10005];
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
// a1 / a2 / a3 / ... / an → 通过加括号可以使 a2 成为分母
// 判断 a1 * a3 * ... * an 是否能被 a2 整除
// 即 a2 / gcd(a1,a2) 继续除以 gcd(..., ai) 最终是否为 1
int den = a[2];
den /= __gcd(a[1], den); // a1 可以约分
for (int i = 3; i <= n; ++i) {
den /= __gcd(den, a[i]);
if (den == 1) break;
}
puts(den == 1 ? "Yes" : "No");
}
return 0;
}复杂度
每个数参与一次 gcd,总时间复杂度
总结
括号结构看似很多,但能否为整数只取决于第二项分母能否被其它项完全约掉。