https://vijos.org/p/1765

这题用白书的方法是n^2的,所以我tle了一个点。。sad。

我稍微优化了一下。

这个题给我最大的感受不是这个题本身,而是我感受到了自己思考以后并认真查错一次提交获得这么高分的感受。

做题一定要认真、仔细。

写这些题最重要的就是仔细,一些细节方面没处理好,那么就会挂了,而陷入调试的泥潭。

想想我以前写的程序,哪个不是这样呢?

首先一定要有个大概的框架了且自己反复论证这样做是正确的(不考虑满分的情况下,可以充当暴力以便对拍和骗分)

一定要反复论证!

然后是在自己写的时候一定要专心,且一定要跟着框架走,如果发现自己之前想的是错的,一定先离开键盘,仔细的再想一遍。

当写完是否庞大的码量后,一定要静态查错,无疑是几个地方:变量名、数组、逻辑、sb错,且一定要反复验证自己代码的逻辑正确性。

之后才测样例。

一般是直接过的。

如果不过那么不要陷入调试的泥潭,一定要重新看一下哪里会错,哪里可能会错。然后对应的在那里调试,而对应的在那里调试那么就要看自己代码的分块性了,分块得好那么就易于调试。

好了。。

以后就这样,不要着急,要知道这是自己在战斗,只是为了解决问题,而不是一昧地去追求代码的美观,而是正确性。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
#include <map>
#include <cassert>
using namespace std;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << (#x) << " = " << (x) << endl
#define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }
#define printarr1(a, b) for1(_, 1, b) cout << a[_] << '\t'; cout << endl
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
inline const int max(const int &a, const int &b) { return a>b?a:b; }
inline const int min(const int &a, const int &b) { return a<b?a:b; } map<string, int> mp;
typedef long long ll;
const int N=105, M=100005;
const ll eps=1e9;
int n, m, ID, a[N], flag, tot, db;
char s[15];
struct node { node *l, *r; bool f, opt; int s; node() { l=r=NULL; f=opt=0; s=0; } }*root=NULL;
struct dat { int s; bool f, opt; dat() { s=0; f=opt=0; } }b[M];
int getid(char *st, int len) {
string s(st, len);
if(mp[s]) return mp[s];
mp[s]=++ID;
return ID;
}
ll cal(node *x) {
if(x==NULL || flag) return 0;
if(!x->opt) {
if(x->f) return a[x->s];
return x->s;
}
ll l=cal(x->l), r=cal(x->r), ret=0;
int opt=x->s;
if(flag) return 0;
if(opt=='/' && r==0) { flag=1; return 0; }
if(opt=='+') ret=l+r;
if(opt=='-') ret=l-r;
if(opt=='*') ret=l*r;
if(opt=='/') ret=l/r;
if(abs(ret)>eps) { flag=1; return 0; }
return ret;
}
void build(int l, int r, node *&x) {
// if(db>1) return;
// ++db;
// assert(l<=r);
if(l==r) {
x=new node();
x->f=b[l].f;
x->s=b[l].s;
return;
}
int p=0, c1=-1, c2=-1;
for1(i, l, r) {
if(!b[i].opt) continue;
if(b[i].s=='(') ++p;
else if(b[i].s==')') --p;
else if(!p && (b[i].s=='+' || b[i].s=='-')) c1=i;
else if(!p && (b[i].s=='*' || b[i].s=='/')) c2=i;
}
if(c1==-1) c1=c2;
if(c1==-1) { build(l+1, r-1, x); return; }
//puts("here"); dbg(c1);
x=new node();
build(l, c1-1, x->l); build(c1+1, r, x->r);
x->opt=1;
x->s=b[c1].s;
}
int main() {
read(n); read(m);
for1(i, 1, n) {
scanf("%s", s);
getid(s, strlen(s));
}
char c=getchar(); while(c=='\n'||c=='\r'||c==' ') c=getchar();
while(c!='\n') {
if(c>='0' && c<='9') {
int r=0;
while(c>='0' && c<='9') r=r*10+c-'0', c=getchar();
b[++tot].s=r;
}
else if((c>='A' && c<='Z') || (c>='a' && c<='z')) {
int len=0;
while((c>='A' && c<='Z') || (c>='a' && c<='z')) s[len++]=c, c=getchar();
s[len]='\0';
b[++tot].s=getid(s, len);
b[tot].f=1;
}
else if(c!='\n') {
b[++tot].opt=1;
b[tot].s=c;
c=getchar();
}
}
build(1, tot, root);
while(m--) {
for1(i, 1, n) read(a[i]);
flag=0;
int ans=cal(root);
if(flag) puts("Error!");
else printf("%d\n", ans);
}
return 0;
}

描述

计算器是生活中的常用计算工具,可以用来计算各种各样的代数式的值。不过它是有些缺点的,一个主要的问题是它只支持常量的运算。对于同样形式的代数式,仅仅是因为常量的不同就需要重新输入一遍。

程序员们则可以使用高级语言中的表达式求值。在Pascal/C++语言中,表达式是一个很基础的概念。表达式中可以出现变量、常量、运算符、括号,甚至各种各样的函数。

这里我们仅考虑这样的表达式:它由52个大小写英文字母、数字'0'~'9',和’(’、’)’、’+’、’-’、’*’、’/'这些符号组成。每 个运算符都只执行双目运算符的功能,即它的左右两侧都必须是可计算的量。特别的,这里使用'/'符号表示整除。而连续的英文字母组成的单词则表示变量名, 且变量名仅由字母组成。为了简化问题,表达式中的常量均为绝对值不超过10^9的自然数,且无前导0。表达式的计算方法和在源程序中是一样的,即小括号优 先级最高、而'*'、'/'运算符优先级高于'+'、‘-’运算符,同一优先级从左到右按顺序计算。

你的任务,就是对于一个给定的表达式,实现它的计算功能。我们将声明N个变量,并在表达式中引用这些变量。然后给出T组数据。每组数据都是N个变量的一组取值。你需要对每组数据计算此时表达式的返回值。

格式

输入格式

输入文件的第一行包括两个整数N, T,依次表示表达式中引用的变量的数目,以及N个变量的需要计算的取值组数。

接下来N行,每行一个由英文字母组成的字符串,依次表示每个变量名。

接下来一行,一个字符串,表示表达式的内容。

接下来T行,每行N个整数,依次表示每个变量这时的取值。

输出格式

输出文件包括T行,第i行表示N个变量取输入的第i组数值时表达式的答案。

如果在运算过程中出现整数被0除,或者运算过程的中间结果的绝对值大于10^9,输出”Error!”;否则输出一个整数,表示运算结果。运算的中间结果指从左到右按优先级顺序计算时得到的每个数值。

样例1

样例输入1[复制]

2 3
x
total
1+(total/x)
1 3
2 155
0 0

样例输出1[复制]

4
78
Error!

限制

1s

提示

20%的数据满足,表达式中没有小括号。

另外20%的数据满足,表达式中没有加法或减法运算。

另外20%的数据满足,表达式中没有乘法或除法运算。

80%的数据(包括上述在内)满足,表达式的长度不超过100。

100%的数据满足,1 <= N <= 100,1 <= T <= 10,变量名长度不超过10,表达式长度不超过100,000。变量的取值和表达式中的常量是绝对值不超过10^9的自然数。所有变量名互不相同。

【vijos】1765 Caculator(代码题)的更多相关文章

  1. 2019前端面试系列——JS高频手写代码题

    实现 new 方法 /* * 1.创建一个空对象 * 2.链接到原型 * 3.绑定this值 * 4.返回新对象 */ // 第一种实现 function createNew() { let obj ...

  2. python面试_总结02_代码题

    - 代码题 1.创建一个函数,接收一个字符串参数,判断其做为Python标识符是否合法. 具体要求: 如果合法则输出 True,否则输出 False. 如果该字符串与Python内置的关键字,或Bif ...

  3. java面试题及答案(基础题122道,代码题19道)

    JAVA相关基础知识 1.面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分, ...

  4. 代码题 — 剑指offer题目、总结

    剑指offer题目总结:  https://www.cnblogs.com/dingxiaoqiang/category/1117681.html 版权归作者所有,任何形式转载请联系作者.作者:马孔多 ...

  5. 转 java面试题及答案(基础题122道,代码题19道)

    JAVA相关基础知识1.面向对象的特征有哪些方面 1.抽象:抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分,暂时 ...

  6. 代码题 — 剑指offer题目、新增题目

     1.剪绳子 给你一根长度为n的绳子,请把绳子剪成m段 (m和n都是整数,n>1并且m>1)每段绳子的长度记为k[0],k[1],...,k[m].请问k[0]*k[1]*...*k[m] ...

  7. 代码题(14)— 合并有序链表、数组、合并K个排序链表

    1.21. 合并两个有序链表 将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 示例: 输入:1->2->4, 1->3->4 输出 ...

  8. 代码题(59)— 字符串相加、字符串相乘、打印最大n位数

    1.415. 字符串相加 给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和. 思路:和链表相加类似,求进位. class Solution { public: string addS ...

  9. 代码题(45)— 下一个排列、第k个排列

    1.31. 下一个排列 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列). 必须原地修改,只 ...

随机推荐

  1. 微信公众号支付调用chooseWXPay提示“errmsg choosewxpay fail”

    微信公众号支付一直提示“errmsg choosewxpay fail”,也没有提示具体错误信息,签名没有问题(签名验证地址:https://pay.weixin.qq.com/wiki/doc/ap ...

  2. Android图片下载以及缓存框架

    实际开发中进行图片下载以及缓存的框架 介绍一下开发中常见图片加载框架的使用和对比一下优缺点. 1.Picasso 框架 在Android中开发,常需要从远程获取图片并显示在客户端,当然我们可以使用原生 ...

  3. ZOJ 2604 Little Brackets DP

    DP: 边界条件:dp[0][j] = 1 递推公式:dp[i][j] = sum{dp[i-k][j] * dp[k-1][j-1] | 0<k≤i} i对括号深度不超过j的,能够唯一表示为( ...

  4. 对正在运行的mysql进行监控

    对正在运行的mysql进行监控,其中一个方式就是查看mysql运行状态. (1)QPS(每秒Query量) QPS = Questions(or Queries) / seconds mysql &g ...

  5. LR11.5 安卓模拟器性能测试

    LR11.5 安卓模拟器性能测试 上一篇 / 下一篇  2013-07-04 08:07:19 / 个人分类:相关知识 查看( 1172 ) / 评论( 1 ) / 评分( 0 / 0 ) 1.首先下 ...

  6. Linux日知录(常用问题笔记)

    http://blog.csdn.net/yizhu2000/article/details/70688420)序言 日有一知,当有一录,自09年来,工作所需,接触开源平台,对Linux常有涉猎,其间 ...

  7. 前端JS脚本将网页表格导出为Excel

    话不多说,上代码! <!DOCTYPE> <html> <head> <title>Excel Test</title> </head ...

  8. Linux系统编程之----》信号

    "===信号========================================================================================= ...

  9. Java 继承、多态与类的复用

    摘要: 本文结合Java的类的复用对面向对象两大特征继承和多态进行了全面的介绍. 首先,我们介绍了继承的实质和意义,并探讨了继承,组合和代理在类的复用方面的异同.紧接着,我们依据继承引入了多态.介绍了 ...

  10. php.ini配置与中国间隔12小时间设置方法

    打开php.ini 配置文件找到date.timezone把=号后面的参数改成这个date.timezone = Etc/GMT+4即可,这样与中国的时间误差即能达到12小时