codeforces 373div1 Sasha and Array 矩阵+线段树

用线段树储存价值和,因为矩阵 a1 * b + a2 * b + a3 * b + a4 * b + a5 * b = (a1 + a2 + a3 + a4 + a5) * b;
然后进行下优化,尽量减少快速幂的运算数量

#include
#include
#include
#include
#define lson i<<1
#define rson (i<<1) + 1
#define maxn 100005
#define LL long long
using namespace std;
int n,k,b,m;
LL mod = 1000000007ll;
//快速幂
struct ma{
     int m[2][2],row,col;
     ma()
     {
         memset(m,0,sizeof(m));
         row = col = 0;
     }
     ma operator * (ma ma1) //乘
     {
        ma ans;
        ans.row = row;
        ans.col = ma1.col;
        for(int i = 0;i < ans.row;i++)
            for(int j = 0;j < ans.col;j++)
            {
                for(int k = 0;k < col;k++)
                {
                    ans.m[i][j] = (ans.m[i][j] + ((LL)m[i][k] * ma1.m[k][j])) % mod;
                }
            }
        return ans;
     }
     ma operator + (ma ma1) //加
     {
         ma ans;
         ans.row = row;
         ans.col = col;
         for(int i = 0;i < row;i++)
             for(int j = 0;j < col;j++)
                 {
                    ans.m[i][j] =  ma1.m[i][j] + m[i][j];
                    ans.m[i][j] %= mod;
                 }
          return  ans;
     }
     ma operator^(int n)  // 快速幂
     {
         ma ans,ma1;
         ans.row = row; ans.col = col;
         for(int i = 0;i < row;i++)
             ans.m[i][i] = 1;

         ma1.row = row;  ma1.col = col;
         for(int i = 0;i < row;i++)
             for(int j = 0;j < col;j++)
                  ma1.m[i][j] = m[i][j];
         while(n)
         {
            if(n&1)ans = ans * ma1;
            ma1 = ma1 * ma1;
            n >>= 1;
         }
         return ans;
     }
}E, mul;
ma va[maxn * 4], add[maxn * 4];
void pushUp(int i)
{
     va[i]  = va[lson] + va[rson];
}
void pushDown(int i)
{
    va[lson] = va[lson] * add[i];
    va[rson] = va[rson] * add[i];
    add[lson] = add[lson] * add[i];
    add[rson] = add[rson] * add[i];
    add[i] = E;
}
void build(int i, int l, int r)
{
     add[i] = E;
     if(l == r)
     {
        int pre;
        scanf("%d", &pre);
        pre--;
        va[i] = mul ^ pre;
        return;
     }
     int mid = (l + r) / 2;
     build(lson , l, mid);
     build(rson , mid + 1, r);
     pushUp(i);
}
void update(int i, int l, int r, int L , int R, ma ADD)
{
     if(l == L && r == R)
     {
          va[i] = va[i] * ADD;
          add[i] = add[i] * ADD;
          return;
     }
     pushDown(i);
     int mid = (l + r) / 2;

     if(R <= mid) update(lson, l, mid, L, R, ADD);
     else if(L > mid) update(rson, mid + 1, r, L, R, ADD);
     else{
         update(lson, l, mid, L , mid, ADD);
         update(rson, mid + 1, r, mid + 1, R, ADD);
     }
     pushUp(i);
}
int query(int i, int l, int r, int L, int R)
{
     if(l == L && r == R)
     {
          return va[i].m[0][0];
     }
     pushDown(i);
     int mid = (l + r) / 2;
     if(R <= mid) return query(lson, l, mid, L , R);
     else if(L > mid) return query(rson, mid + 1, r, L, R);
     else{
         return (query(lson, l, mid, L , mid) + query(rson, mid + 1, r, mid + 1, R))%mod;
     }
}
int main()
{
    E.row = 2, E.col = 2;
    E.m[0][0] = 1, E.m[0][1] = 0;
    E.m[1][0] = 0, E.m[1][1] = 1;
    mul.row = 2, mul.col = 2;
    mul.m[0][0] = 1, mul.m[0][1] = 1;
    mul.m[1][0] = 1, mul.m[1][1] = 0;
    scanf("%d%d", &n,&m);
    build(1, 1, n);
    while(m--)
    {
       int flag;
       scanf("%d", &flag);
       int a, b, c;
       if(flag == 1){
          scanf("%d%d%d", &a, &b, &c);
          ma ADD = (mul ^ c);
          update(1, 1, n, a, b, ADD);
       }
       else {
          scanf("%d%d", &a,&b);
          printf("%d\n", query(1, 1, n, a, b));
       }
    }
    return 0;
}

你可能感兴趣的:(线段树,快速幂)