字符串表达式计算题目

这篇博客介绍了编程竞赛中三种不同类型的表达式求值问题及其解决方案。第一题利用分类处理加法和乘法实现简单表达式求值;第二题通过递归式快速幂和阶乘大表处理包含加减乘除和阶乘的表达式;第三题通过处理括号和不同运算符优先级完成复杂表达式的计算。所有题目都涉及字符串处理和数学运算技巧。
摘要由CSDN通过智能技术生成

链接

[NOIP2013]表达式求值 (nowcoder.com)icon-default.png?t=M3K6https://ac.nowcoder.com/acm/problem/16539

重返小学 (nowcoder.com)https://ac.nowcoder.com/acm/problem/21181表达式计算4 (nowcoder.com)https://ac.nowcoder.com/acm/problem/50999

题目1:NOIP2013]表达式求值


思路: 

 因为题目只有+、*运算,比较简单,所以只需要分类即可

#include<bits/stdc++.h>
#define io ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long int ll;
typedef pair<int,int> PII;
const int N = 1e4,M=1e5+10;
int a[M]; //数值
char op[M]; //操作
int n=1,ans;
int main()
{ 
    while(scanf("%d%[+*]",&a[n],&op[n]) == 2)n++;
    
    n++;
    
    for(int i=1;i<=n;i++)
    {
        int c=a[i]%N;
        for(;i < n && op[i] == '*';i++)
        {
            c*= (a[i+1] % N);
            c%= N;
        }
        ans+=c;
        ans%=N;
    }
    cout<<ans<<endl;
    return 0;
}

题目2:重返小学

 要点:

1.阶乘求值通过打表求解,否则TLE

2.该题使用递归式快速幂可以AC,非递归式只能过66.7%

思路:

通过递归式运算求解值

1.碰到非操作符(转数字)

2.通过下标进行运算(这样不用考虑优先级问题)

运算逻辑:

整体模拟请自行理解想象,递归模拟过于麻烦

#include<bits/stdc++.h>
#define io ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long int ll;
typedef pair<int,int> PII;
const int mod = 65536;
const int N =65536;
const int p = mod;
int f[N],t;
string n;
#define long long int
int ans=0;//答案 
bool flag=true;//确认表达式是否合法
void init()//阶乘大表
{
    f[0]=1;
    for(int i=1;i<mod;i++)f[i]=f[i-1]*i%mod;
}
int qmi(int x, int y)//递归式快速幂
{
    int temp;
    if(y == 0)
        return 1;
    temp = qmi(x, (y/2));
    if (y%2 == 0)
        return (temp*temp)%N;
    else
    {
        if(y>0)
            return (x*temp*temp)%N;
        else
            return ((temp*temp)/x)%N;
    }
}
int qmi1(int a, int k) //快速幂
{
    if(k == 0)return 1;
    
    int res=1;
    while(k)
    {
        if(k & 1) res=(res*a)%p;
        
        k>>=1;
        
        a=(a*a)%p;
    }
    return res;
}
int changenum(int l,int r) //字母转数字
{
    int sum=0;
    for(int i=l;i<=r;i++)
    {
        sum=sum*10+n[i]-'0';
    }
    return sum;
}
int cal(int l,int r)//递归式求解表达式
{
    int pos1=-1,pos2=-1,pos3=-1,pos4=-1;
    for(int i=l;i<=r;i++)
    {
        if(n[i] == '+' || n[i] == '-')pos1=i;
        if(n[i] == '*' || n[i] == '/')pos2=i;
        if(n[i] == '^')pos3=i;
        if(n[i] == '!')pos4=i;
    }
    if(pos1 == -1 && pos2 == -1 && pos3 == -1 && pos4 == -1)
    {
        return changenum(l,r);
    }
    else if(pos1 != -1) //处理加法和减法
    {
        if(n[pos1] == '+') return (cal(l,pos1-1)+cal(pos1+1,r))%N;
        else
        {
            return (cal(l,pos1-1)-cal(pos1+1,r))%N;
        }
    }
    else if(pos2 != -1) 
    {
        if(n[pos2] == '*') return (cal(l,pos2-1)*cal(pos2+1,r))%N;
        else  //特判 除数为0的情况
        {
            if(cal(pos2+1,r) == 0)flag=false;
            else
            {
            return (cal(l,pos2-1)/cal(pos2+1,r))%N;
            }
        }
    }
    else if(pos3 != -1) //处理快速幂
    {
        return qmi(cal(l,pos3-1),cal(pos3+1,r));
    }
    else if(pos4 != -1)
    {
        int c=cal(l,pos4-1);
        return f[c];
    }

    return 0;
}
signed main()
{
    init();
    cin>>t;
    while(t--)
    {
        ans=0;flag=true;
        cin>>n;
        ans=cal(0,n.size()-1);
        if(flag)cout<<ans<<endl;
        else cout<<"ArithmeticException"<<endl;
        
    }
    return 0;
}

题目3:表达式计算4

#include<bits/stdc++.h>
#define io ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long int ll;
typedef pair<int,int> PII;
#define int long long
string a;
int ans;
int qmi(int a, int k) 
{
    if(k == 0)return 1;
    
    int res=1;
    while(k)
    {
        if(k & 1) res=(res*a);
        
        k>>=1;
        
        a=(a*a);
    }
    return res;
}
int changenum(int l,int r) //字母转数字
{
    int sum=0;
    for(int i=l;i<=r;i++)
    {
        sum=sum*10+a[i]-'0';
    }
    return sum;
}
int cal(int l,int r)
{
    int pos1=-1,pos2=-1,pos3=-1,cnt=0;
    for(int i=l;i<=r;i++)
    {
        if(a[i] == '(')cnt++;
        else if(a[i] == ')')cnt--;
        
        if(!cnt)记录括号外的最后一个符号位置,优先级不同的分开记录
        {
        if(a[i] == '+' || a[i] == '-')pos1=i;
        else if(a[i] == '*' || a[i] == '/')pos2=i;
        else if(a[i] == '^')pos3=i;
        }
    }
    if(cnt > 0 && a[l] == '(')return cal(l+1,r);//去掉多余的括号

    else if(cnt < 0 && a[r] == ')')return cal(l,r-1);
    else if(!cnt && pos1 == -1 && pos2 == -1 && pos3 == -1)//判断情况
    {
        if(a[l] == '(' && a[r] ==')')return cal(l+1,r-1);//碰到左右括号
        else//转数字
        {
            return changenum(l,r);
        }
    }
    else if(pos1 != -1)
    {
        if(a[pos1] == '+')return cal(l,pos1-1)+cal(pos1+1,r);
        else
        {
            return cal(l,pos1-1)-cal(pos1+1,r);
        }
    }
    else if(pos2 != -1)
    {
        if(a[pos2] == '*')return cal(l,pos2-1)*cal(pos2+1,r);
        else
        {
            return cal(l,pos2-1)/cal(pos2+1,r);
        }
    }
    else if(pos3 != -1)
    {
        return qmi(cal(l,pos3-1),cal(pos3+1,r));
    }
    
    return 0;
}
signed main()
{
    cin>>a;
    int ans=cal(0,a.size()-1);
    cout<<ans<<endl;
    
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值