• CodeForces 718C Sasha and Array


    线段树。

    线段树维护区间矩阵和,操作都是最简单的线段树。$lazy$标记不要记录乘了几次,直接记录乘了几次之后的矩阵就可以了,不然每次下传的时候再算一遍时间复杂度会提高。

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<bitset>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    const double pi=acos(-1.0),eps=1e-6;
    void File()
    {
        freopen("D:\in.txt","r",stdin);
        freopen("D:\out.txt","w",stdout);
    }
    template <class T>
    inline void read(T &x)
    {
        char c=getchar(); x=0;
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) {x=x*10+c-'0'; c=getchar();}
    }
    
    int mod=1e9+7;
    const int maxn=100010;
    struct Matrix
    {
        int A[3][3]; int R,C;
    }s[4*maxn],t[4*maxn];
    int n,m;
    Matrix Q,Z,P;
    
    Matrix ch(Matrix a,Matrix b)
    {
        Matrix c;
        int i, j, k;
        for (i = 1; i <= a.R; i++)
            for (j = 1; j <= b.C; j++){
                c.A[i][j]=0;
                for (k = 1; k <= a.C; k++){
                    LL aa=(LL)a.A[i][k],bb=(LL)b.A[k][j];
                    LL cc=aa*bb%(LL)mod;
                    int dd=(int)cc;
                    c.A[i][j] = (c.A[i][j] + dd)%mod;
                }
            }
        c.R=a.R; c.C=b.C;
        return c;
    }
    
    Matrix pow(LL p)
    {
        Matrix X,Y;
    
        X.R=2; X.C=2; Y.R=2; Y.C=2;
    
        Y.A[1][1]=1; Y.A[1][2]=0;
        Y.A[2][1]=0; Y.A[2][2]=1;
    
        X.A[1][1]=0; X.A[1][2]=1;
        X.A[2][1]=1; X.A[2][2]=1;
    
        while (p)
        {
            if (p % 2 == 1) Y = ch(Y,X);
            p = p >> 1;
            X = ch(X,X);
        }
        return Y;
    }
    
    void pushUp(int rt)
    {
        s[rt].R=2; s[rt].C=2;
        s[rt].A[1][1]=(s[2*rt].A[1][1]+s[2*rt+1].A[1][1])%mod;
        s[rt].A[1][2]=(s[2*rt].A[1][2]+s[2*rt+1].A[1][2])%mod;
        s[rt].A[2][1]=(s[2*rt].A[2][1]+s[2*rt+1].A[2][1])%mod;
        s[rt].A[2][2]=(s[2*rt].A[2][2]+s[2*rt+1].A[2][2])%mod;
    }
    
    bool check(Matrix x)
    {
        if(x.A[1][1]!=1) return 0;
        if(x.A[1][2]!=0) return 0;
        if(x.A[2][1]!=0) return 0;
        if(x.A[2][2]!=1) return 0;
        return 1;
    }
    
    void pushDown(int rt)
    {
        if(check(t[rt])==1) return;
    
        s[2*rt]=ch(s[2*rt],t[rt]); t[2*rt]=ch(t[2*rt],t[rt]);
        s[2*rt+1]=ch(s[2*rt+1],t[rt]); t[2*rt+1]=ch(t[2*rt+1],t[rt]);
    
        t[rt].A[1][1]=1; t[rt].A[1][2]=0;
        t[rt].A[2][1]=0; t[rt].A[2][2]=1;
    }
    
    void build(int l,int r,int rt)
    {
        t[rt].A[1][1]=1; t[rt].A[1][2]=0;
        t[rt].A[2][1]=0; t[rt].A[2][2]=1;
        t[rt].R=2; t[rt].C=2;
    
        if(l==r)
        {
            LL x; scanf("%lld",&x);
    
            s[rt].R=2; s[rt].C=2;
            s[rt].A[1][1]=1; s[rt].A[1][2]=0;
            s[rt].A[2][1]=0; s[rt].A[2][2]=1;
    
            s[rt]=ch(s[rt],pow(x-1));
            return;
        }
    
        int m=(l+r)/2;
        build(l,m,2*rt);
        build(m+1,r,2*rt+1);
        pushUp(rt);
    }
    
    void update(int L,int R,LL x,int l,int r,int rt)
    {
        if(L<=l&&r<=R)
        {
            s[rt]=ch(s[rt],P);
            t[rt]=ch(t[rt],P);
            return ;
        }
    
        int m=(l+r)/2;
        pushDown(rt);
        if(L<=m) update(L,R,x,l,m,2*rt);
        if(R>m) update(L,R,x,m+1,r,2*rt+1);
        pushUp(rt);
    }
    
    void add(Matrix a)
    {
        Q.A[1][1]=(Q.A[1][1]+a.A[1][1])%mod;
        Q.A[1][2]=(Q.A[1][2]+a.A[1][2])%mod;
        Q.A[2][1]=(Q.A[2][1]+a.A[2][1])%mod;
        Q.A[2][2]=(Q.A[2][2]+a.A[2][2])%mod;
    }
    
    void get(int L,int R,int l,int r,int rt)
    {
        if(L<=l&&r<=R) { add(s[rt]); return ; }
    
        int m=(l+r)/2;
        pushDown(rt);
        if(L<=m) get(L,R,l,m,2*rt);
        if(R>m) get(L,R,m+1,r,2*rt+1);
        pushUp(rt);
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        build(1,n,1);
        for(int i=1;i<=m;i++)
        {
            int op; scanf("%d",&op);
            int L,R; scanf("%d%d",&L,&R);
            if(op==1)
            {
                LL x; scanf("%lld",&x);
                P=pow(x); update(L,R,x,1,n,1);
            }
            else
            {
                Q.R=2; Q.C=2; memset(Q.A,0,sizeof Q.A);
                get(L,R,1,n,1);
                Z.R=1; Z.C=2; Z.A[1][1]=1; Z.A[1][2]=1;
                Z=ch(Z,Q);
                printf("%d
    ",Z.A[1][1]);
            }
        }
        return 0;
    }
  • 相关阅读:
    《Machine Learning in Action》—— 白话贝叶斯,“恰瓜群众”应该恰好瓜还是恰坏瓜
    《Machine Learning in Action》—— 女同学问Taoye,KNN应该怎么玩才能通关
    《Machine Learning in Action》—— Taoye给你讲讲决策树到底是支什么“鬼”
    深度学习炼丹术 —— Taoye不讲码德,又水文了,居然写感知器这么简单的内容
    《Machine Learning in Action》—— 浅谈线性回归的那些事
    《Machine Learning in Action》—— 懂的都懂,不懂的也能懂。非线性支持向量机
    《Machine Learning in Action》—— hao朋友,快来玩啊,决策树呦
    《Machine Learning in Action》—— 剖析支持向量机,优化SMO
    《Machine Learning in Action》—— 剖析支持向量机,单手狂撕线性SVM
    JVM 字节码指令
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5922310.html
Copyright © 2020-2023  润新知