Groundhog and 2-Power Representation

题目描述

在这里插入图片描述

分析

从题目的备注
在这里插入图片描述
中可以看出
这道题的答案要用高精度计算和存储
于是模板先打好

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]);
}

然后因为题目中有二的幂,所以要再打一个高精度版本的快速幂

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;
}

接下来分析一下给定的输入
发现符号^
被括号给代替了
所以要打括号匹配,并进行递归

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;
    }
    return p;
}

括号匹配

    for(int i=1;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(sol(tp+1,i-1))),pre=i+2,ed=i;
            //因为调试时最后的2^1和2^0没加,所以用ed标记
        }
    }

然后输出就AC了

#include <stack>
#include <cstdio>
#include <cstring>
#include <algorithm>
#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;
}
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 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;
    }return p;
}
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];
    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),putchar(10);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值