湖大训练赛1 Shipuratt

Shipura
Time Limit: 20000ms, Special Time Limit:50000ms, Memory Limit:65536KB
Total submit users: 17, Accepted users: 14
Problem 12817 : No special judgement
Problem description

Dr. Suposupo developed a programming language called Shipura. Shipura supports only one binary operator >> and only one unary function S < >.

>> y is evaluated to &lfloor x / 2^y &rfloor (that is, the greatest integer not exceeding x / 2^y), and S< is evaluated to x^2 mod 1,000,000,007 (that is, the remainder when x^2 is divided by1,000,000,007).

The operator >> is left-associative. For example, the expression >> y >> z is interpreted as (x >> y) >> z, not as >> (y >> z). Note that these parentheses do not appear in actual Shipura expressions.

The syntax of Shipura is given (in BNF; Backus-Naur Form) as follows:

expr   ::= term | expr sp ">>" sp term
term   ::= number | "S" sp "<" sp expr sp ">"
sp     ::= "" | sp " "
number ::= digit | number digit
digit  ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"

The start symbol of this syntax is \tt expr that represents an expression in Shipura. In addition, number is an integer between 0 and 1,000,000,000 inclusive, written without extra leading zeros.

Write a program to evaluate Shipura expressions.


Input

The input is a sequence of datasets. Each dataset is represented by a line which contains a valid expression in Shipura.

A line containing a single # indicates the end of the input. You can assume the number of datasets is at most 100 and the total size of the input file does not exceed 2,000,000 bytes.

Output

For each dataset, output a line containing the evaluated value of the expression.



Output

For each dataset, output a line containing the evaluated value of the expression.


Sample Input
S< S< 12 >> 2 > >
123 >> 1 >> 1
1000000000   >>129
S<S<S<S<S<2>>>>>
S  <S< S<2013    >>> 11 >>> 10 >
#
Sample Output
81
30
0
294967268
14592400
Problem Source
JAG Practice Contest for ACM-ICPC Asia Regional 2013

题意:有两个操作运算符S<x>就是将x平方。a>>b就是将a除以2的b次方次。给出这样的一个字符串。求出结果来。

题解:明显两个操作符可以用存入栈中,使用时再调用出来。注意先得处理完所有空格方便接后的判断。比如遇到S就把S压入栈中(我用的0表示S操作),遇到>号要进行判断,后面位置是数字还是S,如果是数字的话直接进行操作,取出栈中符号,如果是S则将>>操作压入栈中(用1表示>>操作)。如果只有一个>,就取出数字,进行S<x>操作,然后还要进行判断前面符号操作是不是>>(1),如果是则进行>>操作。如此类推。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <list>
#include <vector>
using namespace std;
#define N 200010
#define LL __int64
#define M 1000000007
char s[N],ss[N];
stack <LL> num;
stack <LL> go;
LL ksm(LL a,LL b)
{
	if (b==0) return a;
	for (int i=1;i<=b;i++)
	{
		a/=2;
		if (a==0) return 0;
	}
	return a;
}
int main()
{
	//freopen("in.txt","r",stdin);
//	freopen("outt.txt","w",stdout);
	while (gets(ss))
	{
		if (ss[0]=='#') break;
		while (!num.empty()) num.pop();
		while (!go.empty()) go.pop();
		LL l=strlen(ss);
		LL tt=0;
		memset(s,0,sizeof(s));
		for (LL i=0;i<l;i++)
		{
			while (ss[i]==' ') i++;
			s[tt++]=ss[i];
		}
		s[tt]='\0';		
		int i=0;
		l=tt;
		while (i<l)
		{
			if (s[i]=='S')
			{
				go.push(0);
				i+=2;
			}
			if (s[i]>='0' && s[i]<='9')
			{
				LL k=0;
				while (s[i]>='0' && s[i]<='9')
				{
					k=(k*10+s[i]-'0') % M;
					i++;
				}
				num.push(k);
			}
			if (s[i]=='>')
			{
				i++;
				if (!num.empty() && s[i]=='>' && s[i+1]>='0' && s[i+1]<='9')
				{
					LL k=0;
					i++;
					while (s[i]>='0' && s[i]<='9')
					{
						k=(k*10+s[i]-'0') % M;
						i++;
					}
					LL k1=num.top();
					num.pop();
					num.push(ksm(k1,k));
				}
				else
				{
					if (!go.empty() && go.top()==0 && s[i+1]!='S')
					{
						LL k=num.top();
						num.pop();
						k=k % M * k % M;
						num.push(k);
						go.pop();
						while (!go.empty() && go.top()==1)
						{
							k=num.top();
							num.pop();
							LL k1=num.top();
							num.pop();
							num.push(ksm(k1,k));
							go.pop();
						}
					}
					else 
					{
						go.push(1);
						i++;
					}
				}
			}
		}
		LL k;
		k=num.top();
		num.pop();
		cout<<k<<endl;
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值