普及组exp解题报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
普及组exp的解题报告
南京树人国际学校徐韧喆
【题目描述】
对于1 位二进制变量定义两种运算:
运算符运算规则
⊕0⊕0=0
0⊕1=1
1⊕0=1
1⊕1=1
×0×0=0
0×1=0
1×0=0
1×1=1
运算的优先级是:
1. 先计算括号内的,再计算括号外的。
2. “×”运算优先于“⊕”运算,即计算表达式时,先计算×运算,再计算⊕运算。例如:计算表达式A⊕B ×C时,先计算B ×C,其结果再与A 做⊕运算。
现给定一个未完成的表达式,例如_+(_*_),请你在横线处填入数字0 或者1 ,请问
有多少种填法可以使得表达式的值为0 。
【输入】
输入文件名为exp.in ,共2 行。
第1 行为一个整数L,表示给定的表达式中除去横线外的运算符和括号的个数。
第2 行为一个字符串包含L 个字符,其中只包含’(’、’)’、’+’、’*’这4 种字符,其中’(’、’)’是左右括号,’+’、’*’分别表示前面定义的运算符“⊕”和“×”。这行字符按顺序
给出了给定表达式中除去变量外的运算符和括号。
【输出】
输出文件exp.out 共1 行。包含一个整数,即所有的方案数。注意:这个数可能会很大,请输出方案数对10007 取模后的结果。
【样例】
exp.in
4
+(*)
exp.out
3
【数据范围】
对于20% 的数据有0 ≤L ≤10。
对于50% 的数据有0 ≤L ≤1,000。
对于70% 的数据有0 ≤L ≤10,000 。
对于100%的数据有0 ≤L ≤100,000。
对于50% 的数据输入表达式中不含括号。
【问题分析】
这是一道表达式计算的扩展题,对选手最基本的要求就是表达式计算。在一般的表达式计算中,存放结果的栈都是记录计算到某一步的结果,而在这道题中,结果只可能为2个(0或者1),且是知道的,而运算的数字是不一定的,所以在栈中只需存放算到0或者1时的方案数,最后输出到最后算出0的方案数即可。
【算法实现】
一、
首先粗略地说一下表达式计算的方法:
需要使用两个栈,一个存放结果,另一个存放符号。每次读入一个数据,就进入结果栈,如果是符号,则按以下方法:
1、如果是左括号,就直接进栈;
2、如果是右括号,就一直弹栈并加以计算,直到弹到左括号;
3、如果是运算符,则弹栈,直到这个运算符的优先级大于符号栈栈顶的符号的优先级
或是左括号或栈空,然后将运算符进栈;
最后再将栈中残余的符号和结果一直弹到只剩一个结果,这个就是最后的结果。
二、
此题算法的框架整体上是和表达式计算相同的,有以下几个方面不同:
1、需要添加数字的地方应该满足不在右括号的后面或者左括号的前面
2、优先级:“*”的优先级比“+”高
3、运算方法,每一步计算为0或1的方法数:设两个步骤的运算结果经过每个符号到一个结果时,第一个运算结果算出0的方案数为t1,1的方案数为t2,第二个算出0的方案数为t3,算出1的方案数为t4,则有:
当符号是“⊕”时,得到0的方案数为t1*t3,1的方案数:t1*t4+t2*t3+t2*t4
当符号是“×”时,得到0的方案数为t1*t3+t1*t4+t2*t3,1的方案数:t2*t4
用一个栈记录下来即可。
【程序实现】
var str:ansistring;
nn,n,i,top1,top2,kk:longint;
ans1,ans2:array[1..200000] of longint;
fu:array[1..200000] of char;
procedure suan(top1,top2:longint); {计算每一步的方案数}
var t1,t2,t3,t4:longint;
begin
t1:=ans1[top1];t2:=ans2[top1];
t3:=ans1[top1+1];t4:=ans2[top1+1];
if fu[top2]='+' then
begin
ans1[top1]:=t1*t3 mod 10007;
ans2[top1]:=(t1*t4+t2*t4+t2*t3) mod 10007;
end
else
begin
ans1[top1]:=(t1*t3+t1*t4+t2*t3) mod 10007;
ans2[top1]:=t2*t4 mod 10007;
end;
end;
function jisuan(ch:char):longint; {计算优先级}
begin
case ch of
'#','(':jisuan:=0;
'+':jisuan:=1;
'*':jisuan:=2;
end;
end;
begin
assign(input,'exp.in');
assign(output,'exp.out');
reset(input);
rewrite(output);
readln(n);
readln(str);
top1:=0;
fu[1]:='#';
top2:=1;
if str[n]<>')' then nn:=n+1 else nn:=n;
for i:=1 to nn do {表达式运算的过程}
begin
if (i=n+1) or (((i=1) or (str[i-1]<>')')) and (str[i]<>'(')) then begin
inc(top1);
ans1[top1]:=1;
ans2[top1]:=1;
end;
if i<>n+1 then
if str[i]='(' then
begin
inc(top2);
fu[top2]:='(';
end
else
if str[i]=')' then
begin
while fu[top2]<>'(' do
begin
suan(top1-1,top2);
dec(top1);
dec(top2);
end;