noip2019集训测试赛(四)A.fibonacci

2024-04-30 23:18

本文主要是介绍noip2019集训测试赛(四)A.fibonacci,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Description

给定一个长度为 N 的序列 A={a1,a2,…,an} .

M 次操作, 每次操作形如下面两种中的一种:

1 l r x 将 a l , a l + 1 , . . . , a r a_l,a_{l+1},...,a_r al,al+1,...,ar 都加上 x ;

2 l r 求 ∑ i = l r f ( a i ) m o d ( 1 0 9 + 7 ) \sum_{i=l}^rf(a_i)\ mod\ (10^9+7) i=lrf(ai) mod (109+7)

其中 f n f_n fn 为斐波那契数列的第 n 项, 即

{ f n = 1 n = 1 或 n = 2 f n = f n − 1 + f n − 2 n > 2 \left \{ \begin{array}{ll} f_n=1\qquad\qquad\qquad \ \ n=1或n=2\\ f_n=f_{n-1}+f_{n-2}\qquad n>2 \end{array} \right. {fn=1  n=1n=2fn=fn1+fn2n>2


Input

第一行两个数 N,M .

第二行 N 个数 a1,a2,…,an .

接下来 M 行, 每行代表题目描述中的一种操作.


Output

对于每个询问, 输出一行, 表示答案.


Solution

这题是区间修改查询,一看就是线段树,但我们怎么处理序号加x呢?
众所周知,斐波那契数列可以用矩阵快速幂来搞。
所以,我们可以让线段树每一个节点储存一个表示 f ( a i ) f(a_i) f(ai)的矩阵,对于某个节点加x,只要用这个节点的矩阵乘上单位矩阵p的x次方。

那么问题来了,虽然可以处理单点,但区间怎么办?
其实对于一段区间,我们可以直接将矩阵每一位的值加起来再乘(即结合律),举个栗子:

[ f ( 2 ) f ( 3 ) 0 0 ] ∗ [ 0 1 1 1 ] + [ f ( 4 ) f ( 5 ) 0 0 ] ∗ [ 0 1 1 1 ] \quad\begin{bmatrix} f(2)&f(3) \\\\ 0&0 \end{bmatrix} \quad * \quad \begin{bmatrix} 0&1 \\\\ 1&1 \end{bmatrix} \quad+\quad\begin{bmatrix} f(4)&f(5) \\\\ 0&0 \end{bmatrix} \quad*\quad\begin{bmatrix} 0&1 \\\\ 1&1 \end{bmatrix}\quad f(2)0f(3)00111+f(4)0f(5)00111

= [ f ( 2 ) + f ( 4 ) f ( 3 ) + f ( 5 ) 0 0 ] ∗ [ 0 1 1 1 ] = \begin{bmatrix} f(2)+f(4)&f(3)+f(5) \\\\ 0&0 \end{bmatrix}\quad*\quad\begin{bmatrix} 0&1 \\\\ 1&1 \end{bmatrix} =f(2)+f(4)0f(3)+f(5)00111

= [ f ( 3 ) + f ( 5 ) f ( 4 ) + f ( 6 ) 0 0 ] = \begin{bmatrix} f(3)+f(5)&f(4)+f(6 ) \\\\ 0&0 \end{bmatrix} =f(3)+f(5)0f(4)+f(6)0

那么线段树统计区间直接将矩阵加起来就好啦。

因为常数较大,所以要适当卡常,而且应提前处理好每次加x乘的矩阵,保证复杂度。
但是似乎出题人预处理了2的幂,所以跑得比我快。


Code

#include<bits/stdc++.h>
using namespace std;
const long long mod=1e9+7;
long long s[400010];
bool islaz[400010];
struct node{long long a[3][3];node(){memset(a,0,sizeof(a));}
}pp,p,p1,tree[400010],laz[400010];
node func(node a,node b){node c;for(int i=1;i<=2;i++)for(int j=1;j<=2;j++)for(int k=1;k<=2;k++)c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod;return c;
}
void build(int id,int l,int r){if(l==r){p=pp;laz[id]=node();int x=s[l]-1;tree[id].a[1][2]=1;while(x>0){if(x%2==1) tree[id]=func(tree[id],p);p=func(p,p);x/=2;}return;}int mid=(l+r)>>1;build(id*2,l,mid);build(id*2+1,mid+1,r);for(int i=1;i<=2;i++)for(int j=1;j<=2;j++)tree[id].a[i][j]=(tree[id*2].a[i][j]+tree[id*2+1].a[i][j])%mod;
}
void pushdown(int id){if(islaz[id]){islaz[id]=0;tree[id*2]=func(tree[id*2],laz[id]);tree[id*2+1]=func(tree[id*2+1],laz[id]);if(islaz[id*2]) laz[id*2]=func(laz[id*2],laz[id]);else laz[id*2]=laz[id],islaz[id*2]=1;if(islaz[id*2+1]) laz[id*2+1]=func(laz[id*2+1],laz[id]);else laz[id*2+1]=laz[id],islaz[id*2+1]=1;laz[id]=node();} 
}
void update(int id,int l,int r,int ul,int ur){if(ul<=l&&r<=ur){tree[id]=func(tree[id],p1);if(islaz[id]) laz[id]=func(laz[id],p1);else laz[id]=p1,islaz[id]=1;return;}pushdown(id);int mid=(l+r)>>1;if(ul<=mid) update(id*2,l,mid,ul,ur);if(ur>mid) update(id*2+1,mid+1,r,ul,ur);for(int i=1;i<=2;i++)for(int j=1;j<=2;j++)tree[id].a[i][j]=(tree[id*2].a[i][j]+tree[id*2+1].a[i][j])%mod;
}
int query(int id,int l,int r,int ql,int qr){if(ql<=l&&r<=qr) return tree[id].a[1][2]%mod; pushdown(id);int mid=(l+r)>>1,sum=0;if(ql<=mid) sum=(sum+0ll+query(id*2,l,mid,ql,qr)%mod)%mod;if(qr>mid) sum=(sum+0ll+query(id*2+1,mid+1,r,ql,qr)%mod)%mod;return sum; 
}
inline int read(){char c=getchar(); long long x=0,f=1;while(!isdigit(c) && c!='-') c=getchar();if(c=='-') { f=-1; c=getchar(); }while(isdigit(c)) { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); }return x*f;
}
int main(){int n,m,op,l,r,x;n=read(),m=read();for(int i=1;i<=n;i++)s[i]=read();pp.a[1][2]=pp.a[2][1]=pp.a[2][2]=1;build(1,1,n);for(int i=1;i<=m;i++){op=read(),l=read(),r=read();if(op==1){x=read();p1=pp;  p=pp;int x1=x-1;while(x1>0){if(x1%2==1) p1=func(p1,p);p=func(p,p);x1/=2;}update(1,1,n,l,r);}else printf("%d\n",query(1,1,n,l,r)); }
}

这篇关于noip2019集训测试赛(四)A.fibonacci的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/950176

相关文章

如何测试计算机的内存是否存在问题? 判断电脑内存故障的多种方法

《如何测试计算机的内存是否存在问题?判断电脑内存故障的多种方法》内存是电脑中非常重要的组件之一,如果内存出现故障,可能会导致电脑出现各种问题,如蓝屏、死机、程序崩溃等,如何判断内存是否出现故障呢?下... 如果你的电脑是崩溃、冻结还是不稳定,那么它的内存可能有问题。要进行检查,你可以使用Windows 11

性能测试介绍

性能测试是一种测试方法,旨在评估系统、应用程序或组件在现实场景中的性能表现和可靠性。它通常用于衡量系统在不同负载条件下的响应时间、吞吐量、资源利用率、稳定性和可扩展性等关键指标。 为什么要进行性能测试 通过性能测试,可以确定系统是否能够满足预期的性能要求,找出性能瓶颈和潜在的问题,并进行优化和调整。 发现性能瓶颈:性能测试可以帮助发现系统的性能瓶颈,即系统在高负载或高并发情况下可能出现的问题

字节面试 | 如何测试RocketMQ、RocketMQ?

字节面试:RocketMQ是怎么测试的呢? 答: 首先保证消息的消费正确、设计逆向用例,在验证消息内容为空等情况时的消费正确性; 推送大批量MQ,通过Admin控制台查看MQ消费的情况,是否出现消费假死、TPS是否正常等等问题。(上述都是临场发挥,但是RocketMQ真正的测试点,还真的需要探讨) 01 先了解RocketMQ 作为测试也是要简单了解RocketMQ。简单来说,就是一个分

【测试】输入正确用户名和密码,点击登录没有响应的可能性原因

目录 一、前端问题 1. 界面交互问题 2. 输入数据校验问题 二、网络问题 1. 网络连接中断 2. 代理设置问题 三、后端问题 1. 服务器故障 2. 数据库问题 3. 权限问题: 四、其他问题 1. 缓存问题 2. 第三方服务问题 3. 配置问题 一、前端问题 1. 界面交互问题 登录按钮的点击事件未正确绑定,导致点击后无法触发登录操作。 页面可能存在

业务中14个需要进行A/B测试的时刻[信息图]

在本指南中,我们将全面了解有关 A/B测试 的所有内容。 我们将介绍不同类型的A/B测试,如何有效地规划和启动测试,如何评估测试是否成功,您应该关注哪些指标,多年来我们发现的常见错误等等。 什么是A/B测试? A/B测试(有时称为“分割测试”)是一种实验类型,其中您创建两种或多种内容变体——如登录页面、电子邮件或广告——并将它们显示给不同的受众群体,以查看哪一种效果最好。 本质上,A/B测

Verybot之OpenCV应用一:安装与图像采集测试

在Verybot上安装OpenCV是很简单的,只需要执行:         sudo apt-get update         sudo apt-get install libopencv-dev         sudo apt-get install python-opencv         下面就对安装好的OpenCV进行一下测试,编写一个通过USB摄像头采

BIRT 报表的自动化测试

来源:http://www.ibm.com/developerworks/cn/opensource/os-cn-ecl-birttest/如何为 BIRT 报表编写自动化测试用例 BIRT 是一项很受欢迎的报表制作工具,但目前对其的测试还是以人工测试为主。本文介绍了如何对 BIRT 报表进行自动化测试,以及在实际项目中的一些测试实践,从而提高了测试的效率和准确性 -------

可测试,可维护,可移植:上位机软件分层设计的重要性

互联网中,软件工程师岗位会分前端工程师,后端工程师。这是由于互联网软件规模庞大,从业人员众多。前后端分别根据各自需求发展不一样的技术栈。那么上位机软件呢?它规模小,通常一个人就能开发一个项目。它还有必要分前后端吗? 有必要。本文从三个方面论述。分别是可测试,可维护,可移植。 可测试 软件黑盒测试更普遍,但很难覆盖所有应用场景。于是有了接口测试、模块化测试以及单元测试。都是通过降低测试对象

day45-测试平台搭建之前端vue学习-基础4

目录 一、生命周期         1.1.概念         1.2.常用的生命周期钩子         1.3.关于销毁Vue实例         1.4.原理​编辑         1.5.代码 二、非单文件组件         2.1.组件         2.2.使用组件的三大步骤         2.3.注意点         2.4.关于VueComponen

如何成为一个优秀的测试工程师

链接地址:http://blog.csdn.net/KerryZhu/article/details/5250504 我一直在想,如何将自己的测试团队打造成世界一流的团队?流程、测试自动化、创新、扁平式管理、国际标准制定、测试社区贡献、…… 但首先一点是明确的,就是要将每一个测试工程师打造成优秀的测试工程师,优秀的团队必须由优秀的成员构成。所以,先讨论“如何成为一个优秀的测试工程师”,