zoukankan      html  css  js  c++  java
  • CodeForces 1380F Strange Addition 题解

    CF1380F链接

    常见套路(?)

    首先,假设是静态。

    约定“第 (i) 位”是从高到低的。如 (95731) 的第 (2) 位是 (5)

    推一推方程:

    [dp_i = dp_{i-1} imes v_1 + dp_{i-2} imes v_2 ]

    具体地说,设 (t_i) 是第 (i) 位上的数字,(u) 是第 (i-1) 位与第 (i) 位拼成的数字,即 (10t_{i-1} + t_i)。则

    [dp_i = dp_{i-1} imes (t_i + 1) + [10 leq u leq 18]dp_{i-2} imes (19 - u) ]

    然后看到非独立的修改操作,套路就出场了:线段树维护矩阵乘法

    大概就是把 (dp) 的转移换成矩阵乘法,然后用线段树单点修改,维护一些区间的积。

    这里就不展开讨论了,可以找一些资料。

    比如:First Second

    对每个位置 (i) 可构造矩阵

    [egin{pmatrix} 0 & v_{2_i} \ 1 & v_{1_i} end{pmatrix} quad ]

    然后应该就不难了。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define mit map<int,int>::iterator
    #define sit set<int>::iterator
    #define itrm(g,x) for(mit g=x.begin();g!=x.end();g++)
    #define itrs(g,x) for(sit g=x.begin();g!=x.end();g++)
    #define ltype int
    #define rep(i,j,k) for(ltype(i)=(j);(i)<=(k);(i)++)
    #define rap(i,j,k) for(ltype(i)=(j);(i)<(k);(i)++)
    #define per(i,j,k) for(ltype(i)=(j);(i)>=(k);(i)--)
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define mpr make_pair
    #define pb push_back
    #define fastio ios::sync_with_stdio(false)
    const int inf=0x3f3f3f3f,mod=998244353;
    const double pi=3.1415926535897932,eps=1e-6;
    void chmax(int &x,int y){if(x < y) x = y;}
    void chmin(int &x,int y){if(x > y) x = y;}
    #define check(x) if(x >= mod) x -= mod
    int n,m,dp[500005],t[500005];
    char s[500005];
    struct mat{
        int a[2][2];
        mat(){a[0][0] = a[0][1] = a[1][0] = a[1][1] = 0;}
    }E;
    mat operator *(mat a,mat b){
        mat c;
        rep(i,0,1) rep(j,0,1) rep(k,0,1) {c.a[i][j] += (ll)a.a[i][k] * b.a[k][j] % mod;check(c.a[i][j]);}
        return c;
    }
    mat st[500005];
    struct segtree{
        mat dat[1048580];int n;
        void build(int nn)
        {
            n=1;
            while(n<=nn) n<<=1;
            for(int i=n-1;i<2*n-1;i++) dat[i]=st[i - n + 1];
            for(int i=n-2;i>=0;i--) dat[i] = dat[(i<<1)+1] * dat[(i<<1)+2];
        }
        void update(int k,mat a){
            k+=n-1;
            dat[k]=a;
            while(k>0){
                k=(k-1)/2;
                dat[k]=dat[(k<<1)+1]*dat[(k<<1)+2];
            }
        }
        mat query(int l,int r){
            return query(l,r+1,0,0,n);
        }
        mat query(int a,int b,int k,int l,int r){
            if(r<=a||b<=l) return E;
            if(a<=l&&r<=b) return dat[k];
            return query(a,b,(k<<1)+1,l,(l+r)>>1)*query(a,b,(k<<1)+2,(l+r)>>1,r);
        }
    }seg;
    int main()
    {
        E.a[0][0] = E.a[1][1] = 1;
        scanf("%d%d%s",&n,&m,s+1);
        rep(i,1,n) t[i] = s[i] - 48;
        /*dp[0] = 1;
        rep(i,1,n) {
            dp[i] = ((ll)dp[i - 1] * (t[i] + 1))% mod;
            int u = t[i] + t[i - 1] * 10;
            if(i > 1 && 10 <= u && u <= 18) {dp[i] += (ll)dp[i - 2] * (19 - u) % mod;check(dp[i]);}
        }
        printf("%d
    ",dp[n]);*/
        st[0] = E;
        rep(i,1,n) {
            int u = t[i] + t[i - 1] * 10;
            st[i].a[0][0] = 0;
            st[i].a[0][1] = (i > 1 && 10 <= u && u <= 18 ? 19 - u : 0);
            st[i].a[1][0] = 1;
            st[i].a[1][1] = t[i] + 1;
        }
        seg.build(n);
        //mat res = seg.query(1,n);
        //printf("%d %d
    %d %d
    ",res.a[0][0],res.a[0][1],res.a[1][0],res.a[1][1]);
        rep(i,1,m) {
            int a,b;
            scanf("%d%d",&a,&b);
            t[a] = b;
            int u1 = t[a] + t[a - 1] * 10, u2 = t[a + 1] + t[a] * 10;
            st[a].a[0][1] = (a > 1 && 10 <= u1 && u1 <= 18 ? 19 - u1 : 0);
            st[a].a[1][1] = t[a] + 1;
            seg.update(a, st[a]);
            if(a < n) st[a + 1].a[0][1] = (10 <= u2 && u2 <= 18 ? 19 - u2 : 0),seg.update(a + 1, st[a + 1]);
            mat res = seg.query(1,n);
            printf("%d
    ",res.a[1][1]);
        }
        return 0;
    }
    
  • 相关阅读:
    jchdl
    jchdl
    UVa 10256 (判断两个凸包相离) The Great Divide
    UVa 11168 (凸包+点到直线距离) Airport
    LA 2572 (求可见圆盘的数量) Kanazawa
    UVa 10652 (简单凸包) Board Wrapping
    UVa 12304 (6个二维几何问题合集) 2D Geometry 110 in 1!
    UVa 10674 (求两圆公切线) Tangents
    UVa 11796 Dog Distance
    LA 3263 (平面图的欧拉定理) That Nice Euler Circuit
  • 原文地址:https://www.cnblogs.com/yz-beacon-cwk/p/13305041.html
Copyright © 2011-2022 走看看