• P1797 克鲁斯的加减法_NOI导刊2010提高(05)


    首先看题,只有+,-,*。

    考虑开long long直接搞

    首先当做字符串读入

    其中总共有五种类别

    1.一开始只有一个数字

    2.+(x)y

    3.+++……+x

    4.-(x)y

    5.---…-x

    读入数字的话考虑将快读更改

    inline int read(int x){//x表示当前位置
        int s=0;
        while(ch[x]<'0'||ch[x]>'9')x++;//非数字
        while(ch[x]>='0'&&ch[x]<='9')s=s*10+ch[x]-'0',x++;
        return s;
    }

    开个ans记录答案,判断每种运算累积到ans中,最后输出ans。

    for(int i=1;i<=len;++i){
            if(ch[i]=='+'&&ch[i+1]=='('){   //当前为第2种运算 
                int k=read(i+2);            //跳过左括号读入括号内数字 
                while(ch[i]<'0'||ch[i]>'9')i++;
                while(ch[i]>='0'&&ch[i]<='9')i++;
                i++;                        //跳过右括号 
                ans+=read(i)*k;             //读入数字及进行乘法运算累积ans 
            }
            else if(ch[i]=='-'&&ch[i+1]=='('){//当前为第4种运算 
                int k=read(i+2);            
                while(ch[i]<'0'||ch[i]>'9')i++;
                while(ch[i]>='0'&&ch[i]<='9')i++;
                i++;
                ans-=read(i)*k;
            }
            else if(ch[i]=='+'&&ch[i+1]>='0'&&ch[i+1]<='9'){//当前为第3种运算特殊情况 
                ans+=read(i+1);             //只有一个加号 
            }
            else if(ch[i]=='-'&&ch[i+1]>='0'&&ch[i+1]<='9'){//当前为第5种运算特殊情况 
                ans-=read(i+1);
            }
            else if(ch[i]=='+'&&ch[i+1]=='+'){//当前为第3种运算
                int cnt=0;                  //多个加号记录加号个数 
                while(ch[i]=='+')cnt++,i++;
                ans+=read(i)*cnt;           //多加法运算转乘及累积答案 
            }
            else if(ch[i]=='-'&&ch[i+1]=='-'){//当前为第5种运算
                int cnt=0;
                while(ch[i]=='-')cnt++,i++;
                ans-=read(i)*cnt;
            }
            else if(i==1&&ch[i]>='0'&&ch[i]<='9')//第1种运算 
                    ans=read(i);            
        }

    然后60分就到手了。

    答案太大炸了long long。

    将原程序改写为高精,然后我们需要高精加,高精减,高精乘。

    a1,a2数组表示暂时读入的两个数

    将原读入函数更改,分成两个,一个读a1,另一个读a2,这里只提供第一个。

    inline void read1(int x){
        memset(a1,0,sizeof(a1));
        while(ch[x]<'0'||ch[x]>'9')x++;
        while(ch[x]>='0'&&ch[x]<='9')x++;
        x--;
        while(ch[x]>='0'&&ch[x]<='9')a1[++a1[0]]=ch[x]-'0',x--;
    }

    然后计算加减乘的时候大力讨论ans正负问题,ans的正负是打标记实现,正加正直接加;正加负变成正减正;负加负,改为正加正,标记不变;负减负变成正减负;

    在加的时候符号是不变的,减的时候需要判断符号。

    下面是完整AC代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    char ch[210];
    int a1[2000],a2[2000],sum[2000];//a1,a2暂时储存,sum储存乘出来的值 
    int s[20000],ans[20000];
    int f=1;
    
    //读入 
    inline void read1(int x){
        memset(a1,0,sizeof(a1));
        while(ch[x]<'0'||ch[x]>'9')x++;
        while(ch[x]>='0'&&ch[x]<='9')x++;
        x--;
        while(ch[x]>='0'&&ch[x]<='9')a1[++a1[0]]=ch[x]-'0',x--;
    }
    inline void read2(int x){
        memset(a2,0,sizeof(a2));
        while(ch[x]<'0'||ch[x]>'9')x++;
        while(ch[x]>='0'&&ch[x]<='9')x++;
        x--;
        while(ch[x]>='0'&&ch[x]<='9')a2[++a2[0]]=ch[x]-'0',x--;
    }
    
    //高精乘 
    inline void mul(){
        sum[0]=a1[0]+a2[0]-1;
        for(int j=1;j<=a2[0];j++){
            for(int i=1;i<=a1[0];i++){
                sum[i+j-1]+=a1[i]*a2[j];
                sum[i+j]+=sum[i+j-1]/10;
                sum[i+j-1]%=10;
            }
        }
        if(sum[sum[0]+1]>=1) sum[0]++;
        while(sum[sum[0]]==0&&sum[0]>1)--sum[0];
    }
    
    //高精加 
    inline void add(int a[],int b[]){
        memset(s,0,sizeof(s));
        int len=max(a[0],b[0]);
        int g=0;
        for(int i=1;i<=len;i++){
            if(i<=a[0]&&i<=b[0])
                s[i]+=a[i]+b[i]+g;
            else if(i<=a[0])s[i]+=a[i]+g;
            else if(i<=b[0])s[i]+=b[i]+g;
            g=s[i]/10;
            s[i]=s[i]%10;
        }
        if(g)s[++len]=g;
        s[0]=len;
        for(int i=0;i<=len;++i)ans[i]=s[i];
    }
    
    //高精减 
    inline bool com(int a[],int b[]){
        if(a[0]>b[0])return 0;
        if(a[0]<b[0])return 1;
        for(int i=a[0];i>=1;--i){
            if(a[i]<b[i])return 1;
            if(a[i]>b[i])return 0;
        }
        return 0;
    }
    inline void jian(int a[],int b[]){
        if(com(a,b)){
            swap(a,b);
            f=-1;
        }
        else f=1;
        for(int i=1;i<=a[0];++i){
            if(i<=b[0])   //我不知道为啥可能在i<=a[0]&&i>=b[0]的时候b[i]有值
                a[i]-=b[i];
            if(a[i]<0){
                a[i]+=10;
                a[i+1]--;
            }
        }
        while(a[a[0]]==0&&a[0]>1)a[0]--;
        for(int i=0;i<=a[0];++i)
            ans[i]=a[i];
    }
    
    //把int型数拆到数组中 
    inline void dig(int x){
        memset(a1,0,sizeof(a1));
        while(x){
            a1[++a1[0]]=x%10;
            x/=10;
        }
    }
    int main(){
        scanf("%s",ch+1);
        int len=strlen(ch+1);
        for(int i=1;i<=len;++i){
            if(ch[i]=='+'&&ch[i+1]=='('){
                read1(i+2);
                while(ch[i]<'0'||ch[i]>'9')i++;
                while(ch[i]>='0'&&ch[i]<='9')i++;
                i++;
                read2(i);
                mul();
                if(f==1)            //讨论符号,f为1,ans为正,f为-1,ans为负 
                    add(ans,sum);
                else jian(sum,ans);
                memset(sum,0,sizeof(sum));
            }
            else if(ch[i]=='-'&&ch[i+1]=='('){
                read1(i+2);
                while(ch[i]<'0'||ch[i]>'9')i++;
                while(ch[i]>='0'&&ch[i]<='9')i++;
                i++;
                read2(i);
                mul();
                if(f==1)
                    jian(ans,sum);
                else add(ans,sum);
                memset(sum,0,sizeof(sum));
            }
            else if(ch[i]=='+'&&ch[i+1]>='0'&&ch[i+1]<='9'){
                read1(i+1);
                if(f==1)
                add(ans,a1);
                else jian(a1,ans);
            }
            else if(ch[i]=='-'&&ch[i+1]>='0'&&ch[i+1]<='9'){
                read1(i+1);
                if(f==1)jian(ans,a1);
                else add(ans,a1);
            }
            else if(ch[i]=='+'&&ch[i+1]=='+'){
                int cnt=0;
                while(ch[i]=='+')cnt++,i++;
                dig(cnt);
                read2(i);
                mul();
                if(f==1)add(ans,sum);
                else jian(sum,ans);
                memset(sum,0,sizeof(sum));
            }
            else if(ch[i]=='-'&&ch[i+1]=='-'){
                int cnt=0;
                while(ch[i]=='-')cnt++,i++;
                dig(cnt);
                read2(i);
                mul();
                if(f==1)
                    jian(ans,sum);
                else add(ans,sum);
                memset(sum,0,sizeof(sum));
            }
            else if(i==1&&ch[i]>='0'&&ch[i]<='9'){
                read1(i);
                for(int j=0;j<=a1[0];++j)
                    ans[j]=a1[j];
            }
        }
        if(f==-1)printf("-");
        for(int i=ans[0];i>0;--i)
            printf("%d",ans[i]);
        return 0;
    }
  • 相关阅读:
    Java中String类两种实例化的区别(转)
    Linux内核如何装载和启动一个可执行程序(转)
    CentOS 7 下安装jdk1.8(转)
    MySQL中死锁(转)
    CTF取证方法大汇总,建议收藏!
    实战经验|大神战队都在i春秋教你打CTF
    CTF丨从零开始搭建WEB Docker靶场
    业务逻辑漏洞探索之敏感信息泄露
    实战经验丨业务逻辑漏洞探索之活动类漏洞
    漏洞经验分享丨Java审计之XXE(下)
  • 原文地址:https://www.cnblogs.com/sanjinliushi/p/11508295.html
Copyright © 2020-2023  润新知