zoukankan      html  css  js  c++  java
  • 表达式求值 [思维题, 矩阵快速幂]

    表达式求值



    color{red}{正解部分}

    按顺序扫表达式, 记录四个状态,

    S:S: 上一个加号前的总和
    M:M: 上一个加号到最后一个乘号为止的乘积
    T:T: 上一个加号之后的运算结果
    e:1e: 1

    当前位置的字符为 cic_i,

    ci= +:     (S,M,T,e)(S+T,e,0,e)c_i = '+': (S, M, T, e) ightarrow (S+T, e, 0, e)
    ci= ×:     (S,M,T,e)(S,T,0,e)c_i = ' imes': (S,M,T,e) ightarrow (S, T, 0, e)
    ci= k:(S,M,T,e)(S,M,10T+kM,e)c_i = 数字k: (S, M, T, e) ightarrow (S, M, 10T+kM, e)

    矩阵快速幂 加速转移, 最后 S+TS+T 即为答案 .


    color{red}{实现部分}

    #include<bits/stdc++.h>
    #define reg register
    
    const int mod = 998244353;
    
    struct Matrix{
            int C[5][5];
            Matrix(){ memset(C, 0, sizeof C); }
    } add, mul, num, Ans;
    
    Matrix modify(const Matrix &a, const Matrix &b){
            Matrix res;
            for(reg int i = 1; i <= 4; i ++)
                    for(reg int j = 1; j <= 4; j ++)
                            for(reg int k = 1; k <= 4; k ++)
                                    res.C[i][j] = (1ll*res.C[i][j] + (1ll*a.C[i][k]*b.C[k][j]%mod)) % mod;
            return res;
    }
    
    Matrix Ksm(Matrix a, int b){
            Matrix res;
            for(reg int i = 1; i <= 4; i ++) res.C[i][i] = 1;
            while(b){
                    if(b & 1) res = modify(res, a);
                    a = modify(a, a); b >>= 1;
            }
            return res;
    }
    
    int N;
    int r;
    
    char s[20];
    
    void Work(){
            scanf("%d%s", &r, s+1);
            int len = strlen(s+1);
            Matrix Mmp;
            for(reg int i = 1; i <= 4; i ++) Mmp.C[i][i] = 1;
            for(reg int i = 1; i <= len; i ++){
                    if(s[i] == '+') Mmp = modify(Mmp, add);
                    else if(s[i] == '*') Mmp = modify(Mmp, mul);
                    else num.C[2][3] = s[i]-'0', Mmp = modify(Mmp, num);
            }
            Mmp = Ksm(Mmp, r); Ans = modify(Ans, Mmp);
    }
    
    int main(){
            add.C[1][1] = add.C[3][1] = add.C[4][2] = add.C[4][4] = 1;
            mul.C[1][1] = mul.C[3][2] = mul.C[4][4] = 1;
            num.C[1][1] = num.C[2][2] = num.C[4][4] = 1, num.C[3][3] = 10;
            Ans.C[1][2] = Ans.C[1][4] = 1; //
            scanf("%d", &N);
            for(reg int i = 1; i <= N; i ++) Work();
            Ans = modify(Ans, add);
            printf("%d
    ", Ans.C[1][1]);
            return 0;
    }
    
  • 相关阅读:
    HashMap遍历的两种方式
    抽象类和接口的区别是什么
    “用户、组或角色'XXX'在当前数据库中已存在”问题
    FCKEditor在IE10下的不兼容问题解决方法
    ADODB.Connection 错误 '800a0e7a' 未找到提供程序。该程序可能未正确安装。解决方法!
    ASP.NET中Url重写后,打不开真正的Html页面
    运用正则表达式在Asp中过滤Html标签代码的四种不同方法
    静态页分页功能js代码
    .NET生成静态页面的方案总结
    禁止ViewState的3种解决方法
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822454.html
Copyright © 2011-2022 走看看