E. Sasha and Array

这个题目没有特别难,需要自己仔细想想,一开始我想了一个方法,不对,而且还很复杂,然后lj提示了我一下说矩阵乘,然后再仔细想想就知道怎么写了。

这个就是直接把矩阵放到线段树里面去了。

注意优化,降低复杂度。

#include <cstring>
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <queue>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int mod=1e9+;
struct mat
{
ll m[][];
}unite,zero; mat operator*(mat a,mat b){
mat ans;
for(int i=;i<=;i++){
for(int j=;j<=;j++){
ll x = ;
for(int k=;k<=;k++) x+=(a.m[i][k]*b.m[k][j])%mod;
ans.m[i][j]=x%mod;
}
}
return ans;
}
mat operator+(mat a,mat b){
mat ans;
for(int i=;i<=;i++)
for(int j=;j<=;j++)
ans.m[i][j]=(a.m[i][j]+b.m[i][j])%mod;
return ans;
} mat mod_pow(mat a,ll n){
mat ans=unite;
while(n){
if(n&) ans=ans*a;
a=a*a;
n>>=;
}
return ans;
} const int maxn=1e5+;
mat sum[maxn*],a,lazy[maxn*];
ll v[maxn]; void init(){
a.m[][]=a.m[][]=a.m[][]=,a.m[][]=;
for(int i=;i<;i++) unite.m[i][i]=;
for(int i=;i<;i++)
for(int j=;j<;j++) zero.m[i][j]=;
} void push_up(int id){
sum[id]=sum[id<<]+sum[id<<|];
} void build(int id,int l,int r){
lazy[id]=unite;
if(l==r){
sum[id]=mod_pow(a,v[l]);
return ;
}
int mid=(l+r)>>;
build(id<<,l,mid);
build(id<<|,mid+,r);
push_up(id);
} bool same(mat a,mat b){
for(int i=;i<=;i++){
for(int j=;j<=;j++){
if(a.m[i][j]!=b.m[i][j]) return false;
}
}
return true;
} void push_down(int id){
if(same(lazy[id],unite)) return ;
sum[id<<]=sum[id<<]*lazy[id];
sum[id<<|]=sum[id<<|]*lazy[id];
lazy[id<<]=lazy[id<<]*lazy[id];
lazy[id<<|]=lazy[id<<|]*lazy[id];
lazy[id]=unite;
} void update(int id,int l,int r,int x,int y,mat val){
if(x<=l&&y>=r){
lazy[id]=lazy[id]*val;
sum[id]=sum[id]*val;
return ;
}
push_down(id);
int mid=(l+r)>>;
if(x<=mid) update(id<<,l,mid,x,y,val);
if(y>mid) update(id<<|,mid+,r,x,y,val);
push_up(id);
} mat query(int id,int l,int r,int x,int y){
if(x<=l&&y>=r) return sum[id];
mat ans=zero;
int mid=(l+r)>>;
push_down(id);
if(x<=mid) ans=ans+query(id<<,l,mid,x,y);
if(y>mid) ans=ans+query(id<<|,mid+,r,x,y);
return ans;
} int main(){
init();
int n,m;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) scanf("%lld",&v[i]);
build(,,n);
while(m--){
int opt;
ll l,r,x;
scanf("%d",&opt);
if(opt==){
scanf("%lld%lld%lld",&l,&r,&x);
mat val=mod_pow(a,x);
update(,,n,l,r,val);
}
else {
scanf("%lld%lld",&l,&r);
mat ans=query(,,n,l,r);
printf("%lld\n",ans.m[][]);
}
}
return ;
}

E. Sasha and Array 矩阵快速幂 + 线段树的更多相关文章

  1. Codeforces Round #373 (Div. 2) E. Sasha and Array 矩阵快速幂+线段树

    E. Sasha and Array time limit per test 5 seconds memory limit per test 256 megabytes input standard ...

  2. Codeforces 719E [斐波那契区间操作][矩阵快速幂][线段树区间更新]

    /* 题意:给定一个长度为n的序列a. 两种操作: 1.给定区间l r 加上某个数x. 2.查询区间l r sigma(fib(ai)) fib代表斐波那契数列. 思路: 1.矩阵操作,由矩阵快速幂求 ...

  3. 【XSY2524】唯一神 状压DP 矩阵快速幂 FFT

    题目大意 给你一个网格,每个格子有概率是\(1\)或是\(0\).告诉你每个点是\(0\)的概率,求\(1\)的连通块个数\(\bmod d=0\)的概率. 最开始所有格子的概率相等.有\(q\)次修 ...

  4. Wannafly Winter Camp 2019.Day 8 div1 E.Souls-like Game(线段树 矩阵快速幂)

    题目链接 \(998244353\)写成\(99824435\)然后调这个线段树模板1.5h= = 以后要注意常量啊啊啊 \(Description\) 每个位置有一个\(3\times3\)的矩阵, ...

  5. 线段树+矩阵快速幂 Codeforces Round #373 (Div. 2) E

    http://codeforces.com/contest/719/problem/E 题目大意:给你一串数组a,a[i]表示第i个斐波那契数列,有如下操作 ①对[l,r]区间+一个val ②求出[l ...

  6. CF575A Fibonotci [线段树+矩阵快速幂]

    题意 \(s\{\}\) 是一个循环数列 循环节为 \(n\),你可以改掉 \(m\) 项,这 \(m\) 项独立,且不影响循环节 考虑线段树维护矩阵,单点修改最多m次,每次矩阵快速幂就完事了 // ...

  7. hdu4965 Fast Matrix Calculation (矩阵快速幂 结合律

    http://acm.hdu.edu.cn/showproblem.php?pid=4965 2014 Multi-University Training Contest 9 1006 Fast Ma ...

  8. hdu 4291 2012成都赛区网络赛 矩阵快速幂 ***

    分析:假设g(g(g(n)))=g(x),x可能非常大,但是由于mod 10^9+7,所以可以求出x的循环节 求出x的循环节后,假设g(g(g(n)))=g(x)=g(g(y)),即x=g(y),y也 ...

  9. 瓷砖铺放 (状压DP+矩阵快速幂)

    由于方块最多涉及3行,于是考虑将每两行状压起来,dfs搜索每种状态之间的转移. 这样一共有2^12种状态,显然进行矩阵快速幂优化时会超时,便考虑减少状态. 进行两遍bfs,分别为初始状态可以到达的状态 ...

随机推荐

  1. 多级菜单初写(dict使用)

    #!/usr/bin/env python3# -*- coding:utf-8 -*-# name:zzyumap = { "中国":{ "北京":{ &qu ...

  2. 正整数的二进制表示中1的个数计算(使用移位或者n&(n-1))

    第一种:使用n&(n-1)表示来计算有多少个1 int n=127; int count=0; while (n!=0){ count++; n=n&(n-1); } 第二种:使用移位 ...

  3. HTTPS工作流程

    HTTPS工作流程 RSA算法 RSA的密钥分成两个部分: PublicKey 加密数据 验证签名 不能解密 任何人都可以获得 Private Key 数据签名(摘要算法) 解密 加密(不用此功能) ...

  4. C#_关键字:Lock的解释和使用

    定义 lock关键字,互斥锁,通过锁住某一对象从而将语句块({})里面的代码设置为临界区. 线程在线性执行代码时若遇到互斥锁,必须先申请互斥锁的访问权,若访问成功,则继续线性访问互斥锁后的临界区代码块 ...

  5. day18作业

    作业: # 1.编写课上讲解的有参装饰器准备明天默写 def auth(file_type): def outer(func): def inter(*args,**kwargs): if file_ ...

  6. 【Jenkins】插件更改国内源

    最近调试脚本,本机安装了Jenkins,但是安装插件时一直失败.更改升级站点也不生效,究其原因是因为default.json中插件下载地址还https://updates.jenkins.io,升级站 ...

  7. [linux] 小问题:管道符,换行问题等;[nginx]启动,重启,关闭命令;以及升级nginx切换命令

    Lniux换行问题 后面回车不会马上执行本条命令而是换行继续. : 是运行完前面就继续后面的, && 同样是前面正确就运行后面, || 是前面运行不正确就运行后面. | 管道符“|”将 ...

  8. SpringCloud-Hystrix 服务降级、熔断

    Hystrix 是什么? Hystrix 是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时.异常等,Hystrix 能够保证在一个依赖出问题的情况下 ...

  9. DEV gridview 合并单元格

    private void gv_docargo_CellMerge(object sender, DevExpress.XtraGrid.Views.Grid.CellMergeEventArgs e ...

  10. php 对象的调用和引入

    直接上实例: 定义: <?php namespace app\php; class a { ; public function index() { echo "; } static f ...