链接
[NOIP2013]表达式求值 (nowcoder.com)https://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;
}