NYOJ_1013除法表达式

来源:互联网 发布:数控车床编程代码 编辑:程序博客网 时间:2024/05/07 11:14

大体描述:

给出一个除法表达式:X1/X2/X3/…/Xk,其中Xi为正整数。除法表达式应当按照从左到右的顺序求和,例如,表达式1/2/1/2的值为1/4。但是可以在表达式中嵌入括号改变计算顺序,例如,表达式(1/2)/(1/2)的值为1.

输入X1,X2…,Xk,判断是否可以通过添加括号,使表达式的值为整数。K<=10000,Xi<=10^9;


可以分析出来我们只需要判断X1*X3…Xk/X2是否为整数即可。

一:高精度运算,

   由题目所给的范围可以知道,必须利用高精度才能存储X1…Xk的乘积,所以只需要用高精度运算进行K-2次乘法和1次除法即可。

   此方法有点麻烦,只做分析

二:唯一分解定理

   分析:由唯一分解定理,X2=P1^A1*P2^A2…P2*An,(其中Pi为质数)

   所以利用唯一分解定理,我们就只需要依次判断Pi的指数Ai是否不大于X1*X3…Xk里面Pi的指数ai即可。

   给出AC代码如下:

 

 #include <iostream>#include <cstring>#include <stdio.h>using namespace std;int item[10005];int nums[100][2];//long long 类型的数据分解为质数相乘不超过16位int ptot[100];void solve(int num1){    memset(ptot,0,sizeof(ptot));    int num2=nums[0][0];    int i,j;    for(i=1;i<=num2;i++)    {        int p=nums[i][0];        for(j=1;j<=num1;j++)        {            int q=item[j];            if(j==2) continue;            while(q%p==0){q/=p;ptot[i]++;}        }        if(ptot[i]<nums[i][1]){cout<<"NO"<<endl; return;}    }    cout<<"YES"<<endl;}void depart(int m)//分解m    {        int&num = nums[0][0]=0;//nums[0][0]是表头,存放总的个数,用引用比较方便        num = 0;        for (int i = 2; i*i <= m;i++)        if (m%i == 0)        {            nums[++num][0] = i;            nums[num][1] = 0;            do            {                nums[num][1]++;                m /= i;            } while (m%i == 0);//将i除干净        }        if (m > 1)//如果分解到最后m仍然大于1,说明它是一个素数。注意:如果只是判断素因子有哪些,可以没有此处判断,否则必须有此步        {            nums[++num][0] = m;            nums[num][1] = 1;        }    }int main(){    int n;cin>>n;    while(n--){       char c;int i;       for(i=1;;i++)//输入除法表达式       {           scanf("%d",&item[i]);           c=getchar();           if(c=='\n') break;       }       if(i==1) cout<<"YES"<<endl;       else{        depart(item[2]);        solve(i);       }    }    return 0;}        


三:欧几里得算法

分析:我们可以直接约分,依次将X1,X3,…Xk与X2约去它们的最大公约数,如果最后X2为1,则说明可以,反之不行

给出AC代码:

  

   #include <iostream>#include <stdio.h>using namespace std;const int K=10005;int num[K];int gcd(int a, int b){    return b==0?a:gcd(b,a%b);}bool solve(int s){    num[2]/=gcd(num[1],num[2]);    if(num[2]==1) return true;    for(int i=3;i<=s;i++){        num[2]/=gcd(num[2],num[i]);        if(num[2]==1) return true;    }    return false;}int main(){    int n;cin>>n;    while(n--){       char c;int i;       for(i=1;;i++)//除法表达式的输入       {           scanf("%d",&num[i]);           c=getchar();           if(c=='\n') break;       }       if(i==1) cout<<"YES"<<endl;       else {            if(solve(i)) cout<<"YES"<<endl;            else cout<<"NO"<<endl;       }    }    return 0;}        

注:以上方法参考刘汝佳老师的《算法竞赛入门经典》,