• 线段树 + 矩阵 --- ZOJ 3772 Calculate the Function


     Calculate the Function

    Problem's Link:   http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3772


    Mean: 

     

    analyse:

    简单的线段树维护矩阵。

    矩阵乘法的结合律(a * b * c == a * (b * c)),注意矩阵乘法不满足分配率(a *b != b * a)。

     

    令 M[x] = [1 A[x]]
                  [1     0 ] ,
    那么有 [ F[R] ] = M[R] * M[R-1] * ... * M[L+2] * [F[L+1]]
              [F[R-1]]                                                   [ F[L] ] 

     

    线段树节点维护上边等式右边前n - 1项的乘值(假设等式右边有n项)。每次询问O(log(n))。

    Time complexity: O(n*logn)

    Source code: 

    /*
    * this code is made by crazyacking
    * Verdict: Accepted
    * Submission Date: 2015-05-25-20.57
    * Time: 0MS
    * Memory: 137KB
    */
    #include <queue>
    #include <cstdio>
    #include <set>
    #include <string>
    #include <stack>
    #include <cmath>
    #include <climits>
    #include <map>
    #include <cstdlib>
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <cstring>
    #define  LL long long
    #define  ULL unsigned long long
    using namespace std;
    
    const int MAXN = 100100;
    const int MOD = 1000000007;
    struct Mat
    {
        long long m[2][2];
        Mat()
        {
                memset(m, 0, sizeof(m));
        }
        Mat operator * (const Mat &b)
        {
            Mat temp;
            for(int i = 0; i < 2; i++)
                for(int j = 0; j < 2; j++)
                    for(int k = 0; k < 2; k++)
                        temp.m[i][j] = ((m[i][k] * b.m[k][j]) + temp.m[i][j]) % MOD;
            return temp;
        }
    };
    
    struct Node
    {
        int l, r;
        Mat mat;
    };
    Node node[MAXN << 2];
    int a[MAXN];
    
    void Build(int rt, int l, int r)
    {
        int m;
        node[rt].l = l;
        node[rt].r = r;
        if(l == r)
        {
            node[rt].mat.m[0][0] = 1;
            node[rt].mat.m[0][1] = a[l];
            node[rt].mat.m[1][0] = 1;
            node[rt].mat.m[1][1] = 0;
        }
        else
        {
            m = (l + r) >> 1;
            Build(rt << 1, l, m);
            Build(rt << 1 | 1, m + 1, r);
            node[rt].mat = node[rt << 1 | 1].mat * node[rt << 1].mat;//注意顺序
        }
    
    }
    Mat Query(int rt, int ql, int qr)
    {
        int m;
        if(ql == node[rt].l && node[rt].r == qr)
            return node[rt].mat;
        else
        {
            m = (node[rt].l + node[rt].r) >> 1;
            if(qr <= m)
                return Query(rt << 1, ql, qr);
            else if(ql > m)
                return Query(rt << 1 | 1, ql, qr);
            else
                return Query(rt << 1 | 1, m + 1, qr) * Query(rt << 1, ql, m);//注意顺序
        }
    }
    int T, n, m, ql, qr;
    
    int main()
    {
        scanf("%d", &T);
        while(T--)
        {
            Mat res, f;
            scanf("%d%d",&n, &m);
            for(int i = 1; i <= n; i++)
                scanf("%d", &a[i]);
            Build(1, 1, n);
            for(int i = 1; i<= m; i++)
            {
                scanf("%d%d", &ql, &qr);
                if(qr - ql >= 2)
                {
                    f.m[0][0] = a[ql + 1];
                    f.m[1][0] = a[ql];
                    res = Query(1, ql + 2, qr) * f;
                    printf("%d
    ", res.m[0][0]);
                }
                else
                    printf("%d
    ", a[qr]);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    URL提交之前对数据编码
    软件工程概论第三章概括
    软件工程概论第七章概括
    软件工程概论第四章概括
    软件工程概论第五章概括
    软件工程概论第一章概括
    《人月神话》观后感
    软件工程概论第六章概括
    软件工程概论第二章概括
    MySQL语句
  • 原文地址:https://www.cnblogs.com/crazyacking/p/4529012.html
Copyright © 2020-2023  润新知