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. iOS9关键字的简单使用

    在iOS 9 苹果推出了很多关键字, 目的其实很明确, 主要就是提高开发人员的效率, 有益于程序员之间的沟通与交流, 在开发中代码更加规范! 1. nullable 与 nonnull nullabl ...

  2. 采用JSP+JavaBean的方式进行简单的实现用户的网页登陆实例

    我们都知道J2EE中的Model1开发模式,那么下面就让我们一起简单的进行一下回顾,其主要是体现了一个初步的分层的思想: jsp层,业务逻辑层,以及我们的数据库层,主要的作用分别为,jsp层负责与用户 ...

  3. 开源数字媒体资产管理系统:Razuna

    Razuna以一个使用Java语言编写的开源的数字媒体资产管理(Digital Asset Management)系统.功能很强大,可以用于管理各种格式的数字媒体资源. Razuna在本机的安装配置还 ...

  4. (一)UI设计的一些常识

    一.概述 新版本的Xcode似乎框架不明示. UIView:屏幕上看得见摸得着的东西.视图.控件.组件. UIView是一个容器,能容纳其他UIView. UIViewController用来控制UI ...

  5. InfiniDB 修改一行的效率?

    InfiniDB引擎的DML速度比较慢,无论设置自动提交开关为关闭或开启,插入性能都很糟糕,但更新和删除的效率还可以,并且不支持truncate表操作. 删,改 效率高 插入,效率低(测试,在数据量稍 ...

  6. 【Android 应用开发】Android应用的自动更新模块

    . 作者 :万境绝尘  转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/18964835 . 软件的自动更新一般都与Splash界 ...

  7. VS2010 / MFC + OpenCV 2.4.9打开图片

    原文地址:http://www.opencv.org.cn/forum.php?mod=viewthread&tid=30832 第一部分,参考http://jingyan.baidu.com ...

  8. shell中关于sort的-o选项

    sort -o选项意思为将排序后的结果写入文件,但你可能会说我可以重定向啊: sort >file 但如果你要排序文件names里的行再写回排序后的结果: sort names > nam ...

  9. Configure the MySQL account associate to the domain user via MySQL Windows Authentication Plugin

    在此记录如何将之前一次做第三发软件在配置的过程. 将AD user通过代理映射到mysql 用户. 在Mysql官网有这样一段话: The server-side Windows authentica ...

  10. django-debug-toolbar的配置以及使用

    django-debug-toolbar django,web开中,用django-debug-toolbar来调试请求的接口,无疑是完美至极.   可能本人,见识博浅,才说完美至极, 大神,表喷,抱 ...