codeforces 718c Sasha and Array

Posted on 2016-10-25 23:13  ziliuziliu  阅读(150)  评论(0编辑  收藏  举报

直接下放矩阵即可。有点卡常,矩阵乘法一定要直接暴力写,不要for。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<ctime>
#define maxn 100050
#define mod 1000000007
using namespace std;
int n,m,root,tot=0,type,x,y,z,ls[maxn<<2],rs[maxn<<2];
struct matrix
{
    int a[3][3];
}val[maxn<<2],lazy[maxn<<2],base[50],F;
int read()
{
    char ch;int data=0;
    while (ch<'0' || ch>'9') ch=getchar();
    while (ch>='0' && ch<='9')
    {
        data=data*10+ch-'0';
        ch=getchar();
    }
    return data;
}
matrix mul(matrix a,matrix b)
{
    matrix c;
    c.a[1][1]=(1LL*a.a[1][1]*b.a[1][1]+1LL*a.a[1][2]*b.a[2][1])%mod;
    c.a[1][2]=(1LL*a.a[1][1]*b.a[1][2]+1LL*a.a[1][2]*b.a[2][2])%mod;
    c.a[2][1]=(1LL*a.a[2][1]*b.a[1][1]+1LL*a.a[2][2]*b.a[2][1])%mod;
    c.a[2][2]=(1LL*a.a[2][1]*b.a[1][2]+1LL*a.a[2][2]*b.a[2][2])%mod;
    return c;
}
matrix f_pow(int x)
{
    matrix ans=F;int ret=0;
    while (x)
    {
        if (x&1) ans=mul(ans,base[ret]);
        x>>=1;ret++;
    }
    return ans;
}
matrix add(matrix a,matrix b)
{
    matrix c;
    c.a[1][1]=(a.a[1][1]+b.a[1][1])%mod;
    c.a[1][2]=(a.a[1][2]+b.a[1][2])%mod;
    c.a[2][1]=(a.a[2][1]+b.a[2][1])%mod;
    c.a[2][2]=(a.a[2][2]+b.a[2][2])%mod;
    return c;
}
void pushdown(int now,int left,int right)
{
    if (left==right) return;
    lazy[ls[now]]=mul(lazy[ls[now]],lazy[now]);
    lazy[rs[now]]=mul(lazy[rs[now]],lazy[now]);
    val[ls[now]]=mul(val[ls[now]],lazy[now]);
    val[rs[now]]=mul(val[rs[now]],lazy[now]);
    lazy[now]=F;
}
void build(int &now,int left,int right)
{
    now=++tot;lazy[now]=F;
    if (left==right)
    {
        val[now].a[1][1]=0;val[now].a[1][2]=1;
        return;
    }
    int mid=left+right>>1;
    build(ls[now],left,mid);
    build(rs[now],mid+1,right);
    val[now]=add(val[ls[now]],val[rs[now]]);
}
void modify(int now,int left,int right,int l,int r,int x)
{
    pushdown(now,left,right);
    if ((left==l) && (right==r))
    {
        matrix ret=f_pow(x);
        lazy[now]=mul(lazy[now],ret);
        val[now]=mul(val[now],ret);
        return;
    }
    int mid=left+right>>1;
    if (r<=mid) modify(ls[now],left,mid,l,r,x);
    else if (l>=mid+1) modify(rs[now],mid+1,right,l,r,x);
    else 
    {
        modify(ls[now],left,mid,l,mid,x);
        modify(rs[now],mid+1,right,mid+1,r,x);
    }
    val[now]=add(val[ls[now]],val[rs[now]]);
}
matrix ask(int now,int left,int right,int l,int r)
{
    pushdown(now,left,right);
    if ((left==l) && (right==r)) return val[now];
    int mid=left+right>>1;
    if (r<=mid) return ask(ls[now],left,mid,l,r);
    else if (l>=mid+1) return ask(rs[now],mid+1,right,l,r);
    else return add(ask(ls[now],left,mid,l,mid),ask(rs[now],mid+1,right,mid+1,r));
}
int main()
{
    base[0].a[1][1]=0;base[0].a[1][2]=base[0].a[2][1]=base[0].a[2][2]=1;
    F.a[1][1]=F.a[2][2]=1;F.a[1][2]=F.a[2][1]=0;
    for (int i=1;i<=30;i++) base[i]=mul(base[i-1],base[i-1]);
    n=read();m=read();
    build(root,1,n);
    for (int i=1;i<=n;i++)
    {
        x=read();
        modify(root,1,n,i,i,x-1);
    }
    for (int i=1;i<=m;i++)
    {
        type=read();
        if (type==1) 
        {
            x=read();y=read();z=read();
            modify(root,1,n,x,y,z);
        }
        else
        {
            x=read();y=read();
            matrix ret=ask(root,1,n,x,y);
            printf("%d\n",ret.a[1][2]%mod);
        }
    }
    return 0;
}