• 欧几里德算法和唯一分解定理


    刘汝佳《入门经典》上提供了一道经典的题目:

    除法表达式,在NYOJ上可以找到原题,题号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
    首先经过推算可知x1恒为分子,x2恒为分母,而其余的数字都可以通过括号移到分子上去
    那么就可以写成x1*x3*x4........*xk/x2
    只要上面乘积能够整除x2就可以化整。
    首先,可以使用欧几里德算法,对于每一个xi,x2除以xi与x2的最大公约数gcd
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    char ch[50010];  //注意数字最长9位,而且还会有/字符
    int gcd(int x,int y)
    {
        if(x<y) swap(x,y);  //这个判断可以节省一点时间
        return y==0?x:gcd(y,x%y);
    }
    int main()
    {
        int T;
        for(scanf("%d",&T);T;T--)
        {
            scanf("%s",ch);
            int top=0,flag=0;
            int tmp1,tmp2,tmp;
            tmp=0;tmp2=0,tmp1=0;;
            for(int i=0,len=strlen(ch);i<len;i++)
            {
                if(ch[i]>='0'&&ch[i]<='9')
                {
                    tmp=tmp*10+ch[i]-'0';
                    if(i==len-1)
                    {
                        if(top==1)
                        {
                            tmp2=tmp;
                            tmp2/=gcd(tmp2,tmp1);
                        }
                        if(top==0) tmp1=tmp;
                        if(top>1) tmp2/=gcd(tmp2,tmp);
                    }
                }
                else
                {
                    if(top==0) tmp1=tmp;
                    if(top==1)
                    {
                        tmp2=tmp;
                        tmp2/=gcd(tmp2,tmp1);
                    }
                    if(top>1) tmp2/=gcd(tmp2,tmp);
                    top++;
                    tmp=0;
                }
                if(tmp2==1) {flag=1;break;}
            }
            if(flag) puts("YES");
            else     puts("NO");
        }
        return 0;
    }
            
    View Code

    然而这道题还可以利用唯一分解定理求解,而可惜的是10的8次方会有5761455个素数,考虑最坏情况,时间上难以承受
    唯一分解定理:每一个自然数都可以分解成一个或者多个素数相乘的形式(n=p1^a1*p2^a2*.....*pm^am)

    只要分别求得x2和所有分子的pi指数,如果对于某个pi指数x2大于所有分子的话,那就无法化整了

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <map>
    #define SET(a) memset(a,0,sizeof(a))
    using namespace std;
    const int Max=50010;
    char ch[Max];
    int cnt1[100000000],cnt2[100000000];
    void take(int x)
    {
        int flag=0;if(x==2) flag=1;
        for(int i=2;i<=x;i++)
        {
            if(x%i==0)
            {
                while(x%i==0)
                {
                    x/=i;
                    cnt1[i]++;
                }
            }
            if(x==1) break;
        }
    }
    int main()
    {
        int T;
        for(scanf("%d",&T);T;T--)
        {
            scanf("%s",ch);
            int tmp=0,top=0,tmp2=0;
            SET(cnt1);SET(cnt2);
            for(int i=0,len=strlen(ch);i<len;i++)
            {
                if(ch[i]>='0'&&ch[i]<='9')
                {
                    tmp=tmp*10+ch[i]-'0';
                    if(i==len-1)
                    {
                        take(tmp);
                    }
                }
                else
                {
                    if(top==1) tmp2=tmp;
                    if(top!=1) take(tmp);
                    tmp=0;
                    top++;
                }
            }
            int flag=0;
            for(int i=2;i<=tmp2;i++)
            {
                if(tmp2%i==0)
                {
                    while(tmp2%i==0)
                    {
                        cnt2[i]++;
                        tmp2/=i;
                    }
                }
                if(cnt2[i]>cnt1[i]) {flag=1;break;}
                if(tmp2==1) break;
            }
            if(flag) puts("NO");
            else     puts("YES");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    SCCM 2007 部署软件更新
    WPF开发工具
    体验Windows Live Writer写Blog
    图像的灰度和黑白处理算法
    很有用的Sql总结转载
    WPF 体验导航窗口
    WPF 一周练
    WPF 图表
    也说Linq 分组
    WPF 体验对话框调用
  • 原文地址:https://www.cnblogs.com/zsyacm666666/p/5621645.html
Copyright © 2020-2023  润新知