除法表达式
题目:给出除法表达式:
X
1
/
X
2
/
X
3
/
.
.
.
/
X
k
X_1/X_2/X_3/.../X_k
X1/X2/X3/.../Xk,其中
X
i
X_i
Xi是整数。除法表达式应当按照从左到右的顺序求和,例如表达式
1
/
2
/
1
/
2
1/2/1/2
1/2/1/2的值为
1
/
4
1/4
1/4。但可以在表达式中嵌入括号以改变计算顺序,例如表达式
(
1
/
2
)
/
(
1
/
2
)
(1/2)/(1/2)
(1/2)/(1/2)的值为1。
分析:加括号以后一定是一些项在分母上一些项在分子上。如果想要容易整除,分母上的项要尽量少。可以发现,无论怎么加括号,第二项 X 2 X_2 X2一定要放在分母上。其它项呢?发现如果用如下加括号的方式:
E = X 1 / ( X 2 / X 3 / . . . / X k ) = X 1 / X 3 / X 4 / . . . / X k X 2 E=X_1/(X_2/X_3/.../X_k)=\frac{X_1/X_3/X_4/.../X_k}{X_2}\quad E=X1/(X2/X3/.../Xk)=X2X1/X3/X4/.../Xk
只需要判断E是否为整数。直接计算结果很大可能溢出。对于这种大整数的计算可以用高精度运算,但是需要进行k-2次乘法和1次除法,比较麻烦。也可以使用唯一分解定理,暂时不讨论。第三种方法是通过找最大公约数进行约分:对于每个 X i X_i Xi,找到 X i 和 X 2 X_i和X_2 Xi和X2的最大公约数,然后约掉。 X 2 X_2 X2会逐渐变小,如果 X 2 X_2 X2的所有因子都能约掉,即 X 2 = 1 X_2=1 X2=1那么可以整除。如果一直到最后 X 2 X_2 X2还是有约不掉的因子,那么不能整除。寻找最大公约数有一个快速简便的方法,称为欧几里德法或辗转相除法,要能够熟练使用。
#include<iostream>
#include<vector>
using namespace std;
int gcd(int a, int b)
{
return b == 0 ? a : gcd(b, a%b);
}
bool judge(vector<int> v)
{
if(v.size()==1) return true;
if(!v.size() || !v[1]) return false;
int x2 = v[1];
x2 /= gcd(x2, v[0]);
for(int i = 2; i < v.size(); i++)
{
x2 /= gcd(x2, v[i]);
if(x2 == 1) return true;
}
if(x2 == 1) return true;
return false;
}
int main()
{
vector<int> X;
int x;
cout<<"Enter numbers, 'q' to finish: "<<endl;
while(cin>>x)
X.push_back(x);
cout<<"Answer is: "<<(judge(X)?"True":"False");
return 0;
}