P1054 等价表达式

题目描述

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

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

这个选择题中的每个表达式都满足下面的性质:

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

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

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

输入输出格式

输入格式:

输入文件的第一行给出的是题干中的表达式。

第二行是一个整数n(2 <= n <= 26),表示选项的个数。后面n行,每行包括一个选项中的表达式。这n个选项的标号分别是A,B,C,D……

输入中的表达式的长度都不超过50个字符,而且保证选项中总有表达式和题干中的表达式是等价的。

输出格式:

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


写完这道题我真想吐血十升。。。

写完这道题我真想吐血十升。。。

写完这道题我真想吐血十升。。。


两个点:

  1. 完美算法不好写,提供一些质数作为a的值代入计算即可
  2. 中缀表达式转后(前)缀表达式。

  • 中缀表达式转后缀表达式

栈s1存数字或运算符,s2存运算符

从左至右扫描

数字进s1

运算符讨论

若s2栈顶优先级小于进来的,我们认为是合法的(想想为什么等于不行)

否则弹出s2到s1直到合法

括号要多一些判断


非完美算法的细节:

  1. 为了避免爆ll,要mod一个大质数。

质数不能太大,不然依旧会爆

也不能太小,不然负数模会出问题

(幸运数字1000000007)

不能每一步都膜,会很慢

  1. a的取值要小,否则很可能要出问题

  2. a的数量不能多不能少,否则很可能会出问题


总结:非完美算法要在看脸的基础上,多想想


code:

// luogu-judger-enable-o2
#include <cstdio>
#include <cstring>
#include <stack>
#define ll long long
using namespace std;
int n;
ll last[15],now[15];
int is[260];
ll pre[5]={5,7,11,2,3};
ll mod=1000000007;
char C[60];
void init()
{
    for(int i='0';i<='9';i++)
        is[i]=1;
    is[int('(')]=2;
    is[int('+')]=3;
    is[int('-')]=3;
    is[int('*')]=4;
    is[int('^')]=5;
    is[int(')')]=6;
    is[int('a')]=7;
}
int cnt;
void read()
{
    char c=getchar();
    while(!is[c]) c=getchar();
    cnt=-1;
    while(c!='\r')
    {
        if(is[c])
            C[++cnt]=c;
        c=getchar();
    }
}

struct node
{
    int k;//符号1还是数字0
    ll c;//数学或者AS码
    node(){}
    node(int k,ll c)
    {
        this->k=k;
        this->c=c;
    }
};

ll get_pow(ll n1,ll n2)
{
    ll nn=1;
    while(n2)
    {
        nn=nn*n1;
        if(nn>=mod)
            nn%=mod;
        n2--;
    }
    return nn;
}

stack <node > s1,s2;

bool get(char *now,int cnt,int flag)
{
    while(!s1.empty()) s1.pop();
    while(!s2.empty()) s2.pop();
    for(int k=0;k<=4;k++)
    {
        for(int i=0;i<=cnt;i++)
        {
            ll x=0;
            char c=*(now+i);
            if(is[c]==1)
            {
                while(is[c]==1&&i<=cnt) {x=x*10+c-'0';i++;c=*(now+i);}
                node tt(0,x);
                s1.push(tt);
                i--;
            }
            else if(is[c]==7)
            {
                node tt(0,pre[k]);
                s1.push(tt);
            }
            else if(is[c]==6)
            {
                while(!s2.empty())
                {
                    if(s2.top().k&&is[s2.top().c]==2)
                        break;
                    s1.push(s2.top());
                    s2.pop();
                }
                if(s2.empty())
                    return false;
                else
                    s2.pop();
            }
            else
            {
                node tt(1,c);
                while(!s2.empty()&&is[s2.top().c]>=is[c]&&s2.top().c!='('&&c!='(')
                {
                    s1.push(s2.top());
                    s2.pop();
                }
                s2.push(tt);
            }
        }
        while(!s2.empty())
        {
            if(is[s2.top().c]==2)
                return false;
            s1.push(s2.top());
            s2.pop();
        }
        while(!s1.empty())
        {
            s2.push(s1.top());
            //printf("%d ",s1.top().c);
            s1.pop();
        }
        //printf("\n");
        while(!s2.empty())
        {
            node tt=s2.top();
            s2.pop();
            if(tt.k)
            {
                ll t1=s1.top().c;
                s1.pop();
                ll t2=s1.top().c;
                s1.pop();
                ll t3;
                if(char(tt.c)=='+')
                    t3=t1+t2;
                else if(char(tt.c)=='-')
                    t3=t2-t1;
                else if(is[tt.c]==4)
                {
                    t3=t2*t1;
                    if(t3>=mod)
                        t3%=mod;
                }
                else if(is[tt.c]==5)
                    t3=get_pow(t2,t1);
                tt.c=t3;
                tt.k=0;
                s1.push(tt);
            }
            else
                s1.push(tt);
        }
        int ttt=s1.top().c%mod;
        if(flag)
            last[k]=s1.top().c%mod;
        else if(last[k]!=ttt)
            return false;
        s1.pop();
    }
    return true;
}

int main()
{
    init();
    read();
    get(C,cnt,1);
    char c=getchar();
    n=0;
    while(!is[c]) c=getchar();
    while(c!='\r') {n=n*10+c-'0';c=getchar();}
    for(int i=0;i<n;i++)
    {
        read();
        if(get(C,cnt,0))
            printf("%c",char(i+'A'));
    }
    return 0;
}

2018.4.29

洛谷 P1054 解题报告的更多相关文章

  1. 洛谷 P1462 解题报告

    P1462 通往奥格瑞玛的道路 题目背景 在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量 有一天他醒来后发现自己居然到了联盟的主城暴风城 在被众多联盟的士兵攻击后,他决定逃回自己的家乡 ...

  2. 洛谷 P1879 解题报告

    P1879 [USACO06NOV]玉米田Corn Fields 题目描述 农场主\(John\)新买了一块长方形的新牧场,这块牧场被划分成\(M\)行\(N\)列\((1 ≤ M ≤ 12; 1 ≤ ...

  3. 洛谷 P1069 解题报告

    P1069 细胞分裂 题目描述 \(Hanks\)博士是\(BT\) (\(Bio-Tech\),生物技术) 领域的知名专家.现在,他正在为一个细胞实验做准备工作:培养细胞样本. \(Hanks\) ...

  4. 洛谷 P2491 解题报告

    P2491 消防 题目描述 某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000). 这个国家的人对火焰有超越宇宙的热情,所以这个 ...

  5. 洛谷 P2587 解题报告

    P2587 [ZJOI2008]泡泡堂 题目描述 第XXXX届NOI期间,为了加强各省选手之间的交流,组委会决定组织一场省际电子竞技大赛,每一个省的代表队由n名选手组成,比赛的项目是老少咸宜的网络游戏 ...

  6. 洛谷 P1053 解题报告

    P1053 篝火晚会 题目描述 佳佳刚进高中,在军训的时候,由于佳佳吃苦耐劳,很快得到了教官的赏识,成为了"小教官".在军训结束的那天晚上,佳佳被命令组织同学们进行篝火晚会.一共有 ...

  7. 洛谷 P1057 解题报告

    P1057 传球游戏 题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏.这次,老师带着同学们一起做传球游戏. 游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹 ...

  8. 洛谷 P1430 解题报告

    P1430 序列取数 题目描述 给定一个长为\(n\)的整数序列\((n<=1000)\),由\(A\)和\(B\)轮流取数(\(A\)先取).每个人可从序列的左端或右端取若干个数(至少一个), ...

  9. 洛谷 P1613 解题报告

    P1613 跑路 题目描述 小\(A\)的工作不仅繁琐,更有苛刻的规定,要求小\(A\)每天早上在\(6:00\)之前到达公司,否则这个月工资清零.可是小\(A\)偏偏又有赖床的坏毛病.于是为了保住自 ...

随机推荐

  1. MinerQueue.java 访问队列

    MinerQueue.java 访问队列 package com.iteye.injavawetrust.miner; import java.util.HashSet; import java.ut ...

  2. 【Qt编程】基于Qt的词典开发系列<二>--本地词典的设计

    我设计的词典不仅可以实现在线查单词,而且一个重大特色就是具有丰富的本地词典库:我默认加入了八个类型的词典,如下所示: 由于是本人是通信专业,因此加入了华为通信词典.电子工程词典,又由于我喜爱编程,也加 ...

  3. 解决unbuntu14.04上的eclipse自动退出的问题

    新安装的ubuntu14.04版,把以前12.04上正常使用的eclipse拷贝到14.04上后,启动eclipse后,输入代码时出现点"."提示符就会自动重启. jdk是1.7. ...

  4. Oracle Service Bus 11g 的三种方案

    使用<Oracle Service Bus 11g Development Cookbook>中的方案迅速推出一批全新的面向服务和消息的解决方案 2012 年 3 月   (单击图像了解更 ...

  5. 一个操作cvs格式的c++类

    经常需要使用excel,或者把有的数据用excel打开,程序可以生成cvs格式的文件,这样就可以excel打开并处理了,于是找了一个处理cvs的c++类跟大家分享 代码出处找不到了: 代码如下: St ...

  6. 【58】Spring总结之注解(2)

    启用注解配置: 1.context:annotation-config 该配置表示启用注解. 2.context:component-scan base-package="." 该 ...

  7. “《编程珠玑》(第2版)第2章”:B题(向量旋转)

    B题是这样子的: 将一个n元一维向量向左旋转(即循环移位)i个位置.例如,当n=8且i=3时,向量abcdefgh旋转为defghabc.简单的代码使用一个n元的中间向量在n步内完成该工作.你能否仅使 ...

  8. Android高效率编码-细节,控件,架包,功能,工具,开源汇总,你想要的这里都有

    Android高效率编码-细节,控件,架包,功能,工具,开源汇总 其实写博客的初衷也并不是说什么分享技术,毕竟咱还只是个小程序员,最大的目的就是对自我的知识积累,以后万一编码的时候断片了,也可以翻出来 ...

  9. MongoDB 3.0新增特性一览

    转自:http://blog.sina.com.cn/s/blog_48c95a190102vedr.html 引言 在历经版本号修改(2.8版本直接跳到3.0版本)和11个rc版本之后,MongoD ...

  10. orale中如何获取当前月份?

    就本人所知,在oracle中,有两种方式可以提取系统的当前月份: 1.使用extract 函数,具体用法看SQL语句: select extract(month from sysdate) as &q ...