P2651 添加括号III 题解

或许是我太蒟了,想了好久的解法。

此题很明确,我们需要加上若干括号使得最后结果为整数。

明显的,我们在日常的数学计算中,可以发现:设任意分数 x y \dfrac{x}{y} yx x x x , y y y 均为正整数),如果 gcd ⁡ ( x , y ) = y \gcd(x,y)=y gcd(x,y)=y ,那么 x y = x \dfrac{x}{y}=x yx=x ,也就是 x y \dfrac{x}{y} yx 为整数,即 x x x , y y y 可以约分。

这句话是解题的关键。理解这句话之后,我们只需要了解哪些数是分子,哪些数是分母即可判断。

分析可得, a 1 a_1 a1 只能是分子, a 2 a_2 a2 只能是分母,剩余的数可以是分子,也可以是分母。(证明见文末)

为了尽可能使 a 2 a_2 a2 被约分,最优解法就是:将剩余的数和 a 1 a_1 a1 全部处于分子处,分母处只留 a 2 a_2 a2

这样,我们只需要判断约分之后 a 2 a_2 a2是否为1。

如何约分呢?将分子的数不断与 a 2 a_2 a2 求最大公约数(设为 z z z ),那么 a 2 a_2 a2 与这个数就能约去 z z z ,令 a 2 ← a 2 z a_2 \gets \dfrac{a_2}{z} a2za2,就可以实现最大化约分。

思路分析完毕。代码实现如下:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+10;
typedef long long LL;
int t,n;
LL a[MAXN];
LL gcd(LL a,LL b)
{
	return b==0?a:gcd(b,a%b);
}
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
		for(int i=1;i<=n;i++)
		{
			if(i==2) continue;//特别注意过滤a2!!!
			a[2]=a[2]/gcd(a[2],a[i]);//约分
		}
		if(a[2]==1) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}

关于前文的证明(有点粗略,请见谅):

首先,设存在 长度为 n n n 的序列 b 1 , b 2 , . . . , b n b_1,b_2,...,b_n b1,b2,...,bn ,令 r = b 1 / b 2 / b 3 / . . . / b n r=b_1/b_2/b_3/.../b_n r=b1/b2/b3/.../bn ,那么根据 a b c = a × c b \dfrac{a}{\frac{b}{c}}=\dfrac{a \times c}{b} cba=ba×c ,可以得到如下结论:

  1. 如果 n n n 是偶数, r = b 1 × b 3 × . . . × b n − 1 b 2 × b 4 × . . . × b n r=\dfrac{b_1 \times b_3 \times ... \times b_{n-1}}{b_2 \times b_4 \times ... \times b_n} r=b2×b4×...×bnb1×b3×...×bn1
  2. 如果 n n n 是奇数, r = b 1 × b 3 × . . . × b n b 2 × b 4 × . . . × b n − 1 r=\dfrac{b_1 \times b_3 \times ... \times b_n}{b_2 \times b_4 \times ... \times b_{n-1}} r=b2×b4×...×bn1b1×b3×...×bn

所以对于这个序列中的 b i b_i bi ( 1 ≤ i ≤ n 1 \leq i \leq n 1in),如果 i i i 是奇数, b i b_i bi 处于分子处,如果 i i i 是偶数, b i b_i bi 处于分母处。

对于这道题中的 a a a 序列,我们虽然可以通过添加括号,使得 a i a_i ai ( 3 ≤ i ≤ n 3 \leq i \leq n 3in)的位置改变,位于分母还是分子具有不确定性,但是无论如何, a 1 a_1 a1 永远是第 1 位, a 2 a_2 a2 永远是第 2 位,那么 a 1 a_1 a1 只能处于分子处, a 2 a_2 a2 只能处于分母处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值