Groundhog and 2-Power Representation
题目描述
样例
input:
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)
output:
1315
题目大意
给定一个计算式,定义
2
(
a
)
=
2
a
2(a)=2^a
2(a)=2a。
计算结果。
分析
分析数据范围,赤裸裸的高精度。但是题目又更恶心了一点,它把幂换成了括号,因此需要括号匹配之后递归求解。
我要学PYTHON
接下来是
D
N
d
a
l
a
o
DNdalao
DNdalao给的更好的思路。对于上面的求解方式,他发现,
1
0
180
10^{180}
10180恰好在
2
600
2^{600}
2600以内,那么也就是说,对于每个式子,如果去掉了最外面的那层括号,那么里面的结果肯定是小于600的,就可以直接用int的快速幂美滋滋。
接下来直接看代码吧。
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int B=200,M=10000;
struct BigInt//最后的一次快速幂还是要高精的,所以还是要板子
{
ll a[B];
BigInt(){}
BigInt(ll x)
{
a[0]=x;
for(int i=0;i<B-1;i++)
{
a[i+1]=a[i]/M;
a[i]%=M;
}
}
};
BigInt add(BigInt x,BigInt y)
{
BigInt ret;
for(int i=0;i<B;i++)
ret.a[i]=x.a[i]+y.a[i];
for(int i=0;i<B-1;i++)
{
ret.a[i+1]+=ret.a[i]/M;
ret.a[i]%=M;
}
return ret;
}
BigInt mul(BigInt x,BigInt y)
{
BigInt ret;
memset(ret.a,0,sizeof(ret.a));
for(int i=0;i<B;i++)
for(int j=0;i+j<B;j++)
ret.a[i+j]+=x.a[i]*y.a[j];
for(int i=0;i<B-1;i++)
{
ret.a[i+1]+=ret.a[i]/M;
ret.a[i]%=M;
}
return ret;
}
void print(BigInt x)
{
int f=-1;
for(int i=B-1;~i;i--)if(x.a[i]){f=i;break;}
if(f>=1){
if(x.a[f]>0){
for(int i=f;i;i--)
x.a[i]--,x.a[i-1]+=M;
}
else{
for(int i=f;i;i--)
x.a[i]++,x.a[i-1]-=M;
}
for(int i=0;i<B-1;i++)
x.a[i+1]+=x.a[i]/M,x.a[i]%=M;
if(!x.a[f]) f--;
printf("%lld",x.a[f]);
for(int i=f-1;~i;i--)
printf("%04lld",abs(x.a[i]));
}else printf("%lld",x.a[0]);
}//以上为高精压位后的板子
const int N=20010;
char s[N],ss[N];
int mat[N];
stack<int> st;
BigInt ans=BigInt(0);
BigInt ksm_last_order(int b)
{
BigInt a=BigInt(2);
BigInt ret=BigInt(1);
while(b){
if(b&1) ret=mul(ret,a);
a=mul(a,a),b>>=1;
}return ret;
}//最后一次的ksm
int ksm(int b)
{
if(!b) return 1;
int a=2,ret=1;
while(b){
if(b&1) ret*=a;
a*=a,b>>=1;
}return ret;
}//int型的ksm
int sol(int l,int r)
{
int p=0;
for(int i=l;i<=r;i++){
if(s[i]=='(') p+=ksm(sol(i+1,mat[i]-1)),i=mat[i]+1;//递归求解
if(s[i]=='2') p+=2;//如果是直接+2,那么人畜无害
}return p;
}
//((2+(0))+2)+((2+(0)))+((2)+(0))+2+(0)
int main()
{
scanf("%s",ss+1);
int lens=strlen(ss+1),len=0;
for(int i=1;i<=lens;i++) if(ss[i]=='2'&&ss[i+1]=='(') ss[i]='?';
for(int i=1;i<=lens;i++) if(ss[i]!='?') s[++len]=ss[i];//把最外层的"2("解决掉
int p=0,pre=1,ed;
for(int i=1,val;i<=len;i++){
if(s[i]=='(') st.push(i);
if(s[i]==')'){
int tp=st.top();//括弧匹配
st.pop();
mat[tp]=i;
if(tp==pre)//如果栈为空,那么就是当前一段处理完了,这里用最前面的括号来判断
ans=add(ans,ksm_last_order(val=sol(tp+1,i-1))),pre=i+2,ed=i;
}
}
ans=add(ans,sol(ed+1,len));
print(ans),puts("");
}
END
DNdalao的优化真的惊到我了,tql了呀