`
danan.2009
  • 浏览: 12939 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

noip2005 等价表达式

    博客分类:
  • java
 
阅读更多

【问题描述】
明明进了中学之后,学到了代数表达式。有一天,他碰到一个很麻烦的选择题。这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的。

这个题目手算很麻烦,因为明明对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这个问题。假设你是明明,能完成这个任务吗?

这个选择题中的每个表达式都满足下面的性质:
1. 表达式只可能包含一个变量‘a’。
2. 表达式中出现的数都是正整数,而且都小于10000。
3. 表达式中可以包括四种运算‘+’(加),‘-’(减),‘*’(乘),‘^’(乘幂),以及小括号‘(’,‘)’。小括号的优先级最高,其次是‘^’,然后是‘*’,最后是‘+’和‘-’。‘+’和‘-’的优先级是相同的。相同优先级的运算从左到右进行。(注意:运算符‘+’,‘-’,‘*’,‘^’以及小括号‘(’,‘)’都是英文字符)
4. 幂指数只可能是1到10之间的正整数(包括1和10)。
5. 表达式内部,头部或者尾部都可能有一些多余的空格。

下面是一些合理的表达式的例子:

((a^1) ^ 2)^3,a*a+a-a,((a+a)),9999+(a-a)*a,1 + (a -1)^3,1^10^9……

【输入文件】
输入文件equal.in的第一行给出的是题干中的表达式。第二行是一个整数n(2 <= n <= 26),表示选项的个数。后面n行,每行包括一个选项中的表达式。这n个选项的标号分别是A,B,C,D……
输入中的表达式的长度都不超过50个字符,而且保证选项中总有表达式和题干中的表达式是等价的。

【输出文件】
输出文件equal.out包括一行,这一行包括一系列选项的标号,表示哪些选项是和题干中的表达式等价的。选项的标号按照字母顺序排列,而且之间没有空格。

【样例输入】
( a + 1) ^2
3
(a-1)^2+4*a
a + 1+ a
a^2 + 2 * a * 1 + 1^2 + 10 -10 +a –a

【样例输出】
AC

【数据规模】
对于30%的数据,表达式中只可能出现两种运算符‘+’和‘-’;
对于其它的数据,四种运算符‘+’,‘-’,‘*’,‘^’在表达式中都可能出现。
对于全部的数据,表达式中都可能出现小括号‘(’和‘)’。

 

【 问题解答】

在做这个题的时候参考了网友的思路。

 

 

package com.danan;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Scanner;
import java.util.Stack;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Noi05 {

	public static final String IN_PATH = "equal.txt";

	public static final String OU_PATH = "D:/rs.txt";

	private static Logger log = Logger.getLogger("com.danan.Noi05");

	private String express = null;

	private Integer a = null;

	private String exps[] = null;

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		Noi05 noi05 = new Noi05();
		noi05.wirteAnswer();

	}

	public Noi05() {
		super();
		init();
	}

	private void init() {
		Scanner scanner = new Scanner(
				ClassLoader.getSystemResourceAsStream(IN_PATH));
		express = scanner.nextLine();
		a = Integer.parseInt(scanner.nextLine());
		exps = new String[a];
		for (int i = 0; i < a; i++) {
			exps[i] = scanner.nextLine();
		}
		scanner.close();
	}

	public void wirteAnswer() {
		Long result = process(express);
		log.info("result:" + result);
		Long tempRs = null;
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < exps.length; i++) {
			tempRs = process(exps[i]);
			log.info("exps[" + i + "]:" + tempRs);
			if (result.equals(tempRs)) {
				sb.append((char) (i + 65));
			}
		}

		// write result to file
		OutputStream os = null;
		try {
			os = new FileOutputStream(OU_PATH);
			os.write(sb.toString().getBytes());
			log.info("write '" + sb.toString() + "' to File" + OU_PATH);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				os.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

	private Long process(String exp) {
		Stack<String> maskSK = new Stack<String>();
		Stack<Long> numSK = new Stack<Long>();
		Pattern pattern = Pattern.compile("\\D|\\d+");
		Matcher matcher = pattern.matcher(exp);
		String mask = null;

		while (matcher.find()) {
			mask = matcher.group();
			if (isMask(mask)) {
				maskSKProcess(maskSK, numSK, mask);
			} else {
				numSK.push("a".equals(mask) ? a : Long.parseLong(mask));
			}
		}

		while (!maskSK.empty()) {
			calculateAndPutNumStack(maskSK, numSK);
		}

		return numSK.pop();

	}

	private void maskSKProcess(Stack<String> maskSK, Stack<Long> numSK,
			String mask) {

		if (maskSK.empty()) {
			maskSK.push(mask);
		} else {
			Boolean is = isInStack(maskSK.lastElement(), mask);
			if (is == null) {
				maskSK.pop();
			} else if (is) {
				maskSK.push(mask);
			} else {
				calculateAndPutNumStack(maskSK, numSK);
				maskSKProcess(maskSK, numSK, mask);
			}

		}
	}

	private void calculateAndPutNumStack(Stack<String> maskSK, Stack<Long> numSK) {
		Long left = null;
		Long right = null;
		Long rs = null;
		right = numSK.pop();
		left = numSK.pop();
		rs = calculate(maskSK.pop(), left, right);
		numSK.push(rs);
	}

	// if in stack
	public Boolean isInStack(String in, String out) {
		int ing = getGrade(in);
		int oug = getGrade(out);
		ing = (ing == 8 ? 0 : ing);
		return (ing == 0 && oug == 0) ? null : ing < oug;
	}

	private Long calculate(String mask, Long lm, Long rm) {

		if ("+".equals(mask)) {
			return lm + rm;
		} else if ("-".equals(mask)) {
			return lm - rm;
		} else if ("*".equals(mask)) {
			return lm * rm;
		} else if ("^".equals(mask)) {
			return pow(lm, rm);
		}
		return 0L;
	}

	private int getGrade(String mask) {
		if ("(".equals(mask)) {
			return 8;
		}
		if (")".equals(mask)) {
			return 0;
		}
		if ("^".equals(mask)) {
			return 6;
		}
		if ("*".equals(mask)) {
			return 3;
		}
		if ("+".equals(mask) || "-".equals(mask)) {
			return 1;
		}
		return -1;
	}

	private Boolean isMask(String str) {
		return !str.matches("a|\\d+");
	}

	private Long pow(Long a, Long b) {
		if (a == 1)
			return 1L;
		else if (b == 1)
			return a;
		else
			return pow(a, b - 1) * a;
	}

}
 

 

分享到:
评论

相关推荐

    历年NOIP提高组真题汇编(2000-2017)

    此文档大大方便搞OI的同学,共86题题目。 2000~2010,NOIP提高组每年考4题, 2011~2017,NOIP提高组每年考6题, 11*4+7*6=86题。 后续每年都会更新题目(ps:我是搞信息学的)

    NOIP2007初赛提高组PASCAL试题.pdf

    - 命题逻辑中,不同的逻辑表达式可能具有相同的真值表,从而互为等价。 #### 进制数的加法 - 不同进制数之间的加法需要先转换到同一进制下进行,或者直接遵循特定进制下的加法规则。 #### 二叉树的遍历方法 - 先根...

    NOIP2014普及组初赛试题答案C++.pdf

    - **解析**:程序中的问题在于表达式 s=s+1/n;。由于n为整数,1/n的结果也将是整数除法的结果,即1除以任何大于1的整数都将为0。正确的做法应该是使用浮点数运算,即1.0/n。 ##### 14. 设变量 x 为 float 型且已...

    NOIP2007初赛提高组C++试题

    - **解释**:题目12涉及命题逻辑中的蕴含运算,选项A“¬P∨Q”与原命题“P→Q”等价。 #### 数制转换 - **知识点**:不同进制数之间的转换。 - **解释**:题目13考查十六进制和八进制数的加法。选项B“(208C)16”...

    [ZA]NOIP26初赛普及组计算机试题及答案029CSP竞赛比赛CSP考级.pdf

    - **题目12**:考查了简单的循环结构与等价表达式。给定的程序段实现了一个简单的计数功能,其等价的赋值语句是s = a + c。 - **题目13**:考查了while循环结构和continue语句的应用。程序中使用了continue语句跳过...

    NOIP2007AtigaoC.pdf

    NOIP2007全国青少年信息学奥林匹克联赛是中国针对青少年信息学奥林匹克竞赛的初赛,其中提高组C语言试卷涵盖多个计算机科学的基础知识点。以下是对试卷内容所涉及知识点的详细解读。 1. CPU的组成部分包括控制器、...

    NOIP初赛模拟题2.pdf

    **解析**: C++编译器的主要功能是将C++源代码转换为等价的目标码。因此,选项**B**正确。 #### 十四、组合问题 **题目14**: 将三封信投到4个邮筒,最多的投法有( ) **解析**: 每封信有4种投递方式,所以总的...

    广东省汕头市金山中学高一信息技术历年NOIP初赛试题17

    12. **DOS命令等价性**:效果等价的DOS命令是(B) `copy A:*.* B:` 与 `xcopy A:*.* B:`,两者都是将A盘的所有文件复制到B盘。 13. **ASCII码值计算**:已知小写字母'm'的ASCII码值是6D(十六进制),则小写字母'c'的...

    NOIP2010初赛普及组C++题目及答案.pdf

    Q) 等价于 P∨(?P),始终为真。正确答案是 A. P∨(?P∧Q)∨(?P∧?Q)。 4. **Linux可执行文件**:在Linux系统中,可执行文件通常没有特定的扩展名,但常见的可执行文件不会以 .exe、.com 或 .dll 结尾。所以答案是 D...

    ITAT技能大赛C语言模拟试题

    B `w+=-2` 是合法的,等价于 `w = w - 2`;C `k=(a=2,b=3)` 是合法的逗号表达式,将最后的值3赋给k;D `a+=a-=a=3` 首先将a赋值为3,然后a自减,再自加,最终a的值不变,表达式也是合法的。 5. **自增自减运算**...

    C++语言 第4章 循环结构(C++版)_codes.rar

    本章聚焦于C++中的循环结构,这对于理解和编写复杂的算法至关重要,尤其是在参加NOIP(全国青少年信息学奥林匹克联赛)和信奥竞赛时。下面我们将深入探讨几种主要的循环结构及其应用。 1. `while` 循环:这是最基础...

    2010第十六届全国青少年信息学奥林匹克联赛初赛试题参考答案与评分标准.pdf

    全国青少年信息学奥林匹克联赛(NOIP)是中国面向中学生的一项计算机学科竞赛活动,旨在选拔和培养中学生的计算机程序设计能力。从提供的文件内容来看,这是一份关于2010年全国青少年信息学奥林匹克联赛初赛试题的...

    CSP-J 模拟1模拟题附答案

    - **(5) 条件表达式的等价性**:`i==n ? '\n' : ''`等价于`"\n"[i==n]`,故正确答案为**B**。 - **(6) 最劣复杂度**:归并排序的最劣时间复杂度为O(nlogn),与快速排序的平均时间复杂度相同,但快速排序的最坏情况...

    数论 最大约数及其性质 Bezout定理

    6. **集合等价**:对于正整数a和b,所有a和b的线性组合构成的集合与所有(a,b)的倍数构成的集合是相同的。这意味着你可以通过线性组合得到所有由(a,b)倍数组成的数。 7. **多个整数的最大公因子**:扩展到多个整数的...

Global site tag (gtag.js) - Google Analytics