或许是我太蒟了,想了好久的解法。
此题很明确,我们需要加上若干括号使得最后结果为整数。
明显的,我们在日常的数学计算中,可以发现:设任意分数 \(\dfrac{x}{y}\) ( \(x\) , \(y\) 均为正整数),如果 \(\gcd(x,y)=y\) ,那么 \(\dfrac{x}{y}=x\) ,也就是 \(\dfrac{x}{y}\) 为整数,即 \(x\) , \(y\) 可以约分。
这句话是解题的关键。理解这句话之后,我们只需要了解哪些数是分子,哪些数是分母即可判断。
分析可得, \(a_1\) 只能是分子, \(a_2\) 只能是分母,剩余的数可以是分子,也可以是分母。(证明见文末)
为了尽可能使 \(a_2\) 被约分,最优解法就是:将剩余的数和 \(a_1\) 全部处于分子处,分母处只留 \(a_2\) 。
这样,我们只需要判断约分之后 \(a_2\)是否为1。
如何约分呢?将分子的数不断与 \(a_2\) 求最大公约数(设为 \(z\) ),那么 \(a_2\) 与这个数就能约去 \(z\) ,令 \(a_2 \gets \dfrac{a_2}{z}\),就可以实现最大化约分。
思路分析完毕。代码实现如下:
#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\) 的序列 \(b_1,b_2,...,b_n\) ,令 \(r=b_1/b_2/b_3/.../b_n\) ,那么根据 \(\dfrac{a}{\frac{b}{c}}=\dfrac{a \times c}{b}\) ,可以得到如下结论:
所以对于这个序列中的 \(b_i\) (\(1 \leq i \leq n\)),如果 \(i\) 是奇数, \(b_i\) 处于分子处,如果 \(i\) 是偶数, \(b_i\) 处于分母处。
对于这道题中的 \(a\) 序列,我们虽然可以通过添加括号,使得 \(a_i\) (\(3 \leq i \leq n\))的位置改变,位于分母还是分子具有不确定性,但是无论如何, \(a_1\) 永远是第 1 位, \(a_2\) 永远是第 2 位,那么 \(a_1\) 只能处于分子处, \(a_2\) 只能处于分母处。