NYOJ 1013 除法表达式(欧几里德算法+唯一分解定理)
题目链接:
http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=1013
- 描述
-
给出一个这样的除法表达式:X1/X2/X3/···/Xk,其中Xi是正整数。除法表达式应当按照从左到右的顺序求和,例如表达式1/2/1/2的值为1/4。但是可以在表达式中嵌入括号以改变计算顺序,例如表达式(1/2)/(1/2)的值为1.
- 输入
- 首先输入一个N,表示有N组测试数据,
每组数据输入占一行,为一个除法表达式,
输入保证合法。
使表达式的值为整数。k<=10000,Xi<=100000000. - 输出
- 输出YES或NO
- 样例输入
-
1 1/2/1/2
- 样例输出
-
YES
1 /* 2 问题 3 给出一个除法表达式x1/x2/x3/.../xk,其中xi是正整数,问能够通过在表达式中嵌入括号以改变计算顺序,使得表达式的值为1 4 5 解题思路 6 直观的想法暴力,但是随即又想暴力的方法是不行的,因为嵌入括号可以是双重嵌套的。 7 看了解析,先将式子变成E=x1/x2/x3/.../xk=(x1/x3/.../xk)/x2,现在的问题变成了判断E是否为整数 8 采用直接约分,那么每次约掉xi和x2的最大公约数,最后看x2是否为1即可。 9 这类题目刚开始看的时候好像无从下手,但是仔细观察将式子经过适当的变型,就可以将问题转化成熟悉的问题,进而求解。 10 11 具体解法,采用scanf将表达式读入,预处理(将'/'变成' ')后将其赋值为一个string类,再采用流式一个一个读入数字存入x,经过判断 12 输出对应结果即可。 13 14 易错分析,刚开始读入的时候以为都是一位数的数字,后来猛地发现可以是多位数字,这种错误真的是,多读题很重要。 15 */ 16 #include<cstdio> 17 #include<cstring> 18 #include<string> 19 #include<cctype> 20 #include<vector> 21 #include<iostream> 22 #include<sstream> 23 using namespace std; 24 25 const int N=30000; 26 char s[N]; 27 int x[N]; 28 29 int judge(int *x,int len); 30 int gcd(int a,int b){ 31 return b==0?a:gcd(b,a%b); 32 } 33 int lcm(int a,int b){ 34 return a/gcd(a,b)*b; 35 } 36 37 vector<int> vx; 38 string vs; 39 int main() 40 { 41 int T,len,i,j,k,vxx; 42 scanf("%d",&T); 43 while(T--){ 44 scanf("%s",s); 45 len=strlen(s); 46 for(i=0;i<len;i++){ 47 if(s[i] == '/') 48 s[i] = ' '; 49 } 50 vs=s; 51 stringstream ss(vs); 52 j=1; 53 while(ss >> vxx) x[j++]=vxx; 54 55 /*for(i=0;i<j;i++) 56 printf("%d ",x[i]); 57 printf("\n");*/ 58 59 if(judge(x,j)) 60 printf("YES\n"); 61 else 62 printf("NO\n"); 63 } 64 return 0; 65 } 66 67 int judge(int *x,int len) 68 { 69 x[2] /= gcd(x[1],x[2]); 70 for(int i=3;i<len;i++) 71 x[2] /= gcd(x[i],x[2]); 72 return x[2] == 1; 73 }
欢迎交流,共同进步——