zoukankan      html  css  js  c++  java
  • HDU-5238 Calculator

    题目描述

    给定一个关于 (x) 的表达式,形如下例:(×4+2^3+8×6)
    按如下方法计算:((((x×4)+2)^3+8)×6)
    运算符只有 加号,乘号,幂运算三种,给定的式子中有 (n)次运算。
    进行 (m)次给定的操作:

    1.表示对一个给定的 (x) 值,求原式的结果并对 (29393) 取模;

    2.表示将 (k) 位置上的运算符和运算符后面的数字改变。完成这些操作。

    Input

    有多组数据。

    (1≤n,m≤50000)

    Output

    对于每组数据输出答案。

    Sample Input

    2
    5 4
    *4
    +2
    ^3
    +8
    *6
    1 2
    1 3
    2 3 *5
    1 3
    4 3
    *4
    ^4
    +4
    *10
    1 1
    2 3 ^4
    1 1
    

    Sample Output

    Case #1:
    6048
    16512
    468
    Case #2:
    2600
    4107
    

    让我们来看一下这个奇特的模数(29393=7*13*17*19)

    至于有什么用呢?我们先往下看。

    首先,我们需要去快速的查询一个数经过这(n)个操作的值,同时我们需要支持快速修改的操作。

    待修改的数据结构,还有区间查询我们直接就想到的线段树。

    我们该如何转移呢?


    对于当前区间(L,R),编号为(num),未知数为(x)的结果为(F(x,L,R,num))

    考虑两个子区间合并。

    (val=F(x,L,mid,num<<1|1)),即(x)经过左子区间的答案。

    那我们就有了(F(x,L,R,num)=F(val,mid+1,R,num<<1|1))

    于是我们就可以利用线段树快速进行求解的。


    我们仔细看看,模数为(29393),线段数对于每个小于等于模数的数都要储存答案。

    空间复杂度为(O(4*n*模数)),时间复杂度为(O(n*log_n*模数))

    无论是时间还是空间都无法承受。

    现在,让我们再看一下之前所提到的(29393)

    我们把它分解为(7*13*17*19)

    我们发现,对于这(4)个数作为模数的时间和空间复杂度都是可以承受的。

    那么设当前(x)经过这(4)个模数的答案为(res_i),最终答案为(Ans),我们有:

    [egin{cases} Ans=res_1\%p_1 \ Ans=res_2\%p_2 \ Ans=res_3\%p_3 \ Ans=res_4\%p_4 end{cases} ]

    我们直接利用中国剩余定理求解即可。

    #include <cstdio>
    #include <iostream>
    
    using namespace std;
    
    #define LL long long
    #define reg register
    #define clr(a,b) memset(a,b,sizeof a)
    #define Mod(x) (x>=mod)&&(x-=mod)
    #define abs(a) ((a)<0?-(a):(a))
    #define debug(x) cerr<<#x<<"="<<x<<endl;
    #define debug2(x,y) cerr<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl;
    #define debug3(x,y,z) cerr<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl;
    #define rep(a,b,c) for(reg int a=(b),a##_end_=(c); a<=a##_end_; ++a)
    #define ret(a,b,c) for(reg int a=(b),a##_end_=(c); a<a##_end_; ++a)
    #define drep(a,b,c) for(reg int a=(b),a##_end_=(c); a>=a##_end_; --a)
    #define erep(i,G,x) for(int i=(G).Head[x]; i; i=(G).Nxt[i])
    #pragma GCC optimize(2)
    
    inline int Read(void) {
        int res=0,f=1;
        char c;
        while(c=getchar(),c<48||c>57)if(c=='-')f=0;
        do res=(res<<3)+(res<<1)+(c^48);
        while(c=getchar(),c>=48&&c<=57);
        return f?res:-res;
    }
    
    template<class T>inline bool Min(T &a, T const&b) {
        return a>b?a=b,1:0;
    }
    template<class T>inline bool Max(T &a, T const&b) {
        return a<b?a=b,1:0;
    }
    const int N=5e4+5,M=1e5+5,Prime[]= {7,13,17,19};
    
    bool MOP1;
    
    int A[N];
    
    char op[N];
    
    struct SEG {
        int val[5][25][N<<2];
        inline void up(int num) {
            ret(i,0,4)ret(j,0,Prime[i]) {
                int nxt=val[i][j][num<<1];
                val[i][j][num]=val[i][nxt][num<<1|1];
            }
        }
        inline int calc(int a,char op,int b,int mod) {
            if(op=='+')return (a+b)%mod;
            if(op=='*')return (a*b)%mod;
            int res=1;
            while(b) {
                if(b&1)res=res*a%mod;
                a=a*a%mod,b>>=1;
            }
            return res;
        }
        inline void build(int L,int R,int num) {
            if(L==R) {
                rep(i,0,3)ret(j,0,Prime[i])val[i][j][num]=calc(j,op[L],A[L],Prime[i]);
                return;
            }
            int mid=(L+R)>>1;
            build(L,mid,num<<1);
            build(mid+1,R,num<<1|1);
            up(num);
        }
        inline void update(int L,int R,int num,int pos) {
            if(L==R) {
                rep(i,0,3)ret(j,0,Prime[i])val[i][j][num]=calc(j,op[L],A[L],Prime[i]);
                return;
            }
            int mid=(L+R)>>1;
            if(pos<=mid)update(L,mid,num<<1,pos);
            else update(mid+1,R,num<<1|1,pos);
            up(num);
        }
    } tr;
    
    int n,res[N],mod[N],a[N],pos[N];
    
    int Exgcd(int a, int b, int &x, int &y) {
        if(!b) {
            x=1,y=0;
            return a;
        }
        int g=Exgcd(b,a%b,y,x);
        y-=a/b*x;
        return g;
    }
    
    inline int Excrt(void) {
        mod[1]=7,mod[2]=13,mod[3]=17,mod[4]=19;
        int M=mod[1],ans=res[1],x,y;
        rep(i,2,4) {
            int g=Exgcd(M,mod[i],x,y);
            x*=(res[i]-ans)/g,y=mod[i]/g,x=(x%y+y)%y;
            ans=M*x+ans,M=M/g*mod[i],ans%=M;
        }
        int z=(ans%M+M)%M;
        return z;
    }
    
    bool MOP2;
    
    inline void _main(void) {
        int T=Read(),Case=0;
        while(T--) {
            printf("Case #%d:
    ",++Case);
            int n,m;
            scanf("%d%d",&n,&m),getchar();
            char c;
            rep(i,1,n)scanf("%c%d",op+i,&A[i]),getchar();
            tr.build(1,n,1);
            while(m--) {
                int Op,pos;
                scanf("%d%d",&Op,&pos);
                if(Op==1) {
                    rep(i,0,3)res[i+1]=tr.val[i][pos%Prime[i]][1];
                    printf("%d
    ",Excrt());
                } else {
                    getchar(),scanf("%c%d",op+pos,&A[pos]);
                    tr.update(1,n,1,pos);
                }
            }
        }
    }
    
    signed main() {
        _main();
        return 0;
    }
    
  • 相关阅读:
    vue 重定向
    vue 通过插槽分发内容
    vue 表单输入绑定 checkbox
    jq enter键发送
    vue footer点击变色
    vue computed和methods 计算属性和侦听器
    实时监听input输入情况
    关于Input输入框蓝色外框的操作
    鼠标悬浮指针变手
    鼠标悬浮样式
  • 原文地址:https://www.cnblogs.com/dsjkafdsaf/p/11572887.html
Copyright © 2011-2022 走看看