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. Python学习笔记 - 字符串和编码

    #!/usr/bin/env python3 # -*- coding: utf-8 -*- #第一行注释是为了告诉Linux/OS X系统, #这是一个Python可执行程序,Windows系统会忽 ...

  2. 6、Libgdx文件处理

    (官网:www.libgdx.cn) 简介 Libgdx应用运行在四个不同的平台中:桌面系统(Windows,Linux,Mac OS X等等),Android,iOS和JavaScript或者Web ...

  3. STL - string(典型操作demo)

    1String概念  string是STL的字符串类型,通常用来表示字符串.而在使用string之前,字符串通常是用char*表示的.string与char*都可以用来表示字符串,那么二者有什么区别呢 ...

  4. GRUB与Linux系统修复(第二版)

    GRUB配置解析 配置文件保存在 /boot/grub/grub.conf[/boot分区最好应该单独划分出来] 软链接保存在 /etc/grub.conf 1.grub.conf文件分析 defau ...

  5. 【UML 建模】UML建模语言入门 -- 静态图详解 类图 对象图 包图 静态图建模实战

    发现个好东西思维导图, 最近开始用MindManager整理博客 . 作者 :万境绝尘  转载请注明出处 : http://blog.csdn.net/shulianghan/article/deta ...

  6. RecyclerView详解

    RecyclerView是support-v7包中的新组件,是一个强大的滑动组件,与经典的ListView相比,同样拥有item回收复用的功能,但是直接把viewholder的实现封装起来,用户只要实 ...

  7. C#中任意类型数据转成JSON格式

    /// <summary>    /// List转成json     /// </summary>    /// <typeparam name="T&quo ...

  8. 分别修改Cube每个面的贴图UV(Unity3D开发之十八)

    猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/46611169 ...

  9. windows下c语言获取程序当前的执行目录,读文件的代码片

    代码如下: #include "stdafx.h" #include "stdlib.h" #include <direct.h> #include ...

  10. 解决Cell重用内容混乱的几种简单方法,有些方法会增加内存

    重用实现分析 查看UITableView头文件,会找到NSMutableArray*  visiableCells,和NSMutableDictnery* reusableTableCells两个结构 ...