关闭

jzoj3588 【中山市选2014】J语言 (表达式解析)

199人阅读 评论(0) 收藏 举报
分类:

超长题面

J语言作为一门编程语言,诞生于20世纪90年代…………..

好学的小H今天又学到了一种新东西——J语言。显然,J语言的背景已经被小H忘得一干二净了,但是小H仍然记得J语言中有趣的数学计算——向量计算。

在J语言中,向量,标量和操作符是基本的组成元素,但是在小H的印象中,J语言中最有趣的就是它的语法,好学的小H也曾经认真研究J语言的语法并且进行了化简。在小H简化了J语言的语法中,用X来表示向量,用N来表示向量X的长度。

简化版J语言的规则如下:

操作符中有有二元操作符,“+”,“-”,“”,而对应操作数可以是两个标量,两个向量,或则一个标量和一个向量。(当两个向量运算时,为对应位分别计算,例如(1,2,3) (2,3,4) = (2,6,12),当一个标量和一个向量运算时,当成标量和向量的每一位运算,例如(1,2,3) * 5 = (5,10,15)

操作符中也有一元操作符,包括负数运算符“-”和平方运算符“:”,其操作数可以为标量和向量。(向量取平方运算符时表示为每一位都取平方,例如:(1, 2, 3) = (1, 4, 9),标量取平方时即数学意义上的平方,例如*:4 = 16)

求和运算符“+/”,该运算符只能作用于向量,能让向量求和为标量,例如+/(1,2,3) = 6

J操作符的运算顺序为从右到左,并且忽略优先级,需要优先计算的部分将用括号改变优先顺序(允许嵌套括号)。

小H化简的J语言还有一个限制——最高阶数的限制,我们这样定义一个表达数的阶数:

标量(数字, ‘N’ ,求和运算符“+/”的结果)的阶数为0

‘X’的复杂度为1 ;

加减法的阶数是其操作数的阶数的最大值;

乘法的阶数是其操作数的阶数的总和;

一元平方的阶数是其操作数的阶数的两倍。

例如,表达式“(3-+/::X)-X**:X”的阶数是3 ,而它的子表达式“::X”的阶数是4 。

小H找到了一道以前写过简化版J语言的表达式,但是别忘了小H只是喜欢思考而不喜欢计算。现在,小H想请你帮他计算一下给定表达式的答案,并且将最终答案取模10^9(必须保证结果非负,即如果求余后是负数要加上10^9), 当然小H还清晰的记得他写下的表达式在运算过程中阶数不会超过10。

100%数据,n<=100000,长度<=100000

分析

一眼看,次数不超过10,那表达式肯定是以X为主元的多项式形式进行运算。
但是一直在想如何兼容所有运算,其实是忽略了一个东西:
X^0={1,1,1,….}
这样可以把标量看作是{5,5,5,5,…}这样的向量,表示为多项式形式就是{5,0,0,0,0…},参与运算即可.

那就很简单了,加减法显然, 平方与乘法就类似多项式乘法,用10*10的时间做. 求和运算预处理一下X^k的各个位置和即可。
搞清楚运算怎么做之后,
再用一个栈,倒着扫(优先级从右到左)做表达式解析即可。 注意是可以存在类似–(..),–X这样的表达式的。
我的(代码复杂度被吊打)表达式解析大概思路:
遇到)入栈一个单位元素,单位元素与A运算都是A.
然后每次读入一个value(X或N或数字),与之前合并,再读入下一个操作符,假如是双目就存到wait等待合并,否则立即执行.
遇到(就将当前括号的元素(栈顶)与上一层元素(栈顶前一个)合并,并退栈.

#include <iostream>
#include <cstring>
#include <cstdio>
#define VEC 1
#define EMP -666
#define NUM 2

using namespace std;
typedef long long ll;

const ll N = 100100,mo = 1e9;
struct value{
    ll a[11];
    value() {memset(a,0,sizeof a);}
} sd,v[N],ept,LEN;
ll n,sl,a[N],b[N];
char ts[N],s[N];
value ele[N];
ll tot,wait[N],p;
ll sum[10];

//1 +
//2 -
//3 *
//4 *:
//5 +/
int getop() {
    if (s[p]=='+') {p++; return 1;}
    if (s[p]=='-') {p++; return 2;}
    if (s[p]=='*') {p++; return 3;}
    if (s[p]==':') {p+=2; return 4;}
    if (s[p]=='/') {p+=2; return 5;}
}
value ret;

value getva() {
    if (s[p]=='X') {p++; return sd;}
    if (s[p]=='N') {p++; return LEN;}
    int st=p;
    while (s[p]>='0' && s[p]<='9') p++;
    ret=value();
    for (int i=p-1; i>=st; i--) ret.a[0]=ret.a[0]*10+s[i]-'0';
    return ret;
}
value mult(value a,value b) {
    ret=value();
    for (int i=0; i<=10; i++) for (int j=0; j<=10; j++) if (i+j<=10) {
        ret.a[i+j]=(ret.a[i+j]+a.a[i]*b.a[j])%mo;
    }else break;
    return ret;
}
value qf(value a) {
    for (int i=0; i<=10; i++) a.a[i]=-a.a[i];
    return a;
}
value add(value a,value b) {
    ret=value();
    for (int i=0; i<=10; i++) ret.a[i]=(a.a[i]+b.a[i])%mo;
    return ret;
}
value operate(value a,int type,value b) {
    if (b.a[0] == EMP) return a;
    if (type==1) return add(a,b);
    if (type==2) return add(a,qf(b));
    if (type==3) return mult(a,b);
}
value operate(value a,int type) {
    if (type==4) return mult(a,a);
    if (type==5) {
        ll su=0;
        for (int i=0; i<=10; i++) su=(su+a.a[i]*sum[i])%mo;
        ret=value(),ret.a[0]=su;
        return ret;
    }
}
void getnexop() {
    while (s[p]!='(') { //此value前有操作符 
        int t=getop();
        if (t<=3) { 
            if (t==2 && s[p]=='-')  {
                ele[tot]=qf(ele[tot]);
                continue;
            }
            wait[tot]=t; //双目操作符放入wait
            break;
        } else ele[tot]=operate(ele[tot],t);
    }
}
int main() {
    freopen("2.in","r",stdin);
    cin>>n;
    for (ll i=1; i<=n; i++) scanf("%lld",&a[i]);
    for (int i=1; i<=n; i++) b[i]=1;
    for (int i=0; i<=10; i++) {
        for (int j=1; j<=n; j++) {
            if (i) b[j]=b[j]*a[j]%mo;
            sum[i]=(sum[i]+b[j])%mo;
        }
    }

    sd.a[1]=1; LEN.a[0]=n;

    scanf("%s",ts+1); sl=strlen(ts+1);
    for (int i=1; i<=sl; i++) s[i]=ts[sl-i+1];
    ele[++tot].a[0]=EMP;
    for (p=1; p<=sl;) {
        if (s[p]==')') {
            ele[++tot].a[0]=EMP; //新建空value 
            p++;
        } else if (s[p]=='(') {
            if (wait[tot]==2)  //先处理wait中的单目- 
                ele[tot]=qf(ele[tot]),wait[tot]=0;
            //merge前一个ele
            ele[tot-1]=operate(ele[tot],wait[tot-1],ele[tot-1]);
            wait[tot-1]=0;
            tot--; p++;
            getnexop();

        } else {
            value tv=getva();
//          if (wait[tot]) 一定要合并 
                ele[tot]=operate(tv,wait[tot],ele[tot]);
                wait[tot]=0;
            getnexop();
        }
    }
    if (wait[tot]==2) ele[tot]=qf(ele[tot]),wait[tot]=0;
    cout<<(ele[1].a[0]+mo)%mo<<endl;
}
0
0
查看评论

中山市选2014 解题报告 By BPM136

题目不告诉乃们 T1 投票 题目理解1:输出占每个人投票总数的百分比,最终得分65分 题目理解2:输出占有效票的百分比,过不了样例 题目理解3: 输出占投票人的百分比,最终得分100分 考点:字符串的读入(尤其对于C++),双关键字快排和语文水平 期望得分100  ...
  • BPM136
  • BPM136
  • 2016-03-19 09:13
  • 326

jzoj3587 【中山市选2014】dwarf tower

题面Vasya在玩一个叫做”Dwarf Tower”的游戏,这个游戏中有n个不同的物品,它们的编号为1到n。现在Vasya想得到编号为1的物品。获得一个物品有两种方式:1. 直接购买该物品,第i件物品花费的钱为ci2. 用两件其他物品合成所需的物品,一共有m种合成方式。 请帮助Vasya用最少的钱获...
  • jokerwyt
  • jokerwyt
  • 2018-01-20 19:47
  • 68

jzoj 2746.【2012中山市选】选数排列(pick) 二分答案+dp

Description给出N个数,我们需要选择其中的R x C个数,,把它们填入一个R x C的矩阵(R行C列)中。我们先定义一个函数D(i)代表第i行中最大的数和最小的数之差。对于整个矩阵,定义F为矩阵中D(i) (1<=i<=R)的最大值。我们需要F的值最少,你能求出最少可能达到的...
  • liangzihao1
  • liangzihao1
  • 2018-01-18 17:47
  • 31

【中山市选2014】图

Description:一个图有n+m个顶点,顶点分黑白两种颜色,其中编号1~n的为白色顶点,n+1~n+m的为黑色顶点。对于任意一个白色顶点vi,有且仅有a个不同的白色顶点和b个不同的黑色顶点与之相连。对于任意一个黑色顶点ui,有且仅有c个不同的白色顶点和d个不同的黑色顶点与之相连。你的任务是根据...
  • Cold_Chair
  • Cold_Chair
  • 2018-01-20 16:34
  • 100

【中山市选2013】蓄养

Description 平面上有N颗树,标号从1到N,每颗树有坐标(Xi, Yi)。要求在平面上找几棵树,在一些树之间建篱笆形成一个闭合图形(篱笆不能在除了树以外的地方相交,形成的图形面积不能为0).求最小可能围成的面积。 Input 第一行输入N。 然后N行第i行输入第i棵树的坐标Xi和Y...
  • Eric1561759334
  • Eric1561759334
  • 2018-01-19 12:34
  • 74

【中山市选2014】投票

Description 有n个候选人要竞选主席,有m个人要投票。每个人只能投一票,如果某个人投了超过一票或者不投票,那么这个人的投票将视为非法。 给出m个人的投票情况,你的任务是统计投票情况,然后按照获得投票数从高到低将候选人排序,如果获得的投票数相同,则按照候选人的输入顺序从小到大排序。 I...
  • Eric1561759334
  • Eric1561759334
  • 2018-01-20 16:12
  • 31

SSL P2516 2014年中山市选拔赛 dwarf tower

题目大意: 给出N个物品直接购买的价格,以及M组合成方式,即物品x与物品y可以合成物品z,求出获得第1个物品的最小花费。 题解: spfa: d[i]表示合成第i个物品的最小值。 1.d[i]的初值是一开始直接购买第i个物品的值。 2.m组x,y,z,对于每组x,y,z,可以变成2条权值...
  • Gx_Man_VIP
  • Gx_Man_VIP
  • 2017-03-28 19:47
  • 154

JZOJsenior3587.【中山市选2014】dwarf tower

problemDescriptionVasya在玩一个叫做”Dwarf Tower”的游戏,这个游戏中有n个不同的物品,它们的编号为1到n。现在Vasya想得到编号为1的物品。获得一个物品有两种方式:1. 直接购买该物品,第i件物品花费的钱为ci2. 用两件其他物品合成所需的物品,一共有m种合成方式...
  • enjoy_pascal
  • enjoy_pascal
  • 2018-01-20 15:29
  • 74

Gym 100269D Dwarf Tower(最短路)

思路:给你m个交换条件就是相当于m条路,然后求一发最短路就可以了 #include using namespace std; const int maxn = 10000+500; int d[maxn]; struct Node { int x,y; Node(){}; Node(...
  • qq_21057881
  • qq_21057881
  • 2016-07-19 08:46
  • 333

【中山市选2008】小树

【中山市选2008】小树Description Input Output Sample Input Input1: 1Input2: 2 0 1 2Input3: 3 0 1 1 0 2 2Sample Output Output1: 0.00Output2: 2.00Ou...
  • white_elephant
  • white_elephant
  • 2016-05-28 16:08
  • 387
    个人资料
    • 访问:40038次
    • 积分:1926
    • 等级:
    • 排名:千里之外
    • 原创:153篇
    • 转载:1篇
    • 译文:0篇
    • 评论:17条
    最新评论