华南理工大学“三七互娱杯”程序设计竞赛(重现赛)B HRY and fibonacci

链接:https://ac.nowcoder.com/acm/contest/874/B
来源:牛客网
 

题目描述

HRY is a pupil. He has just learned about Fibonacci sequence recently, and he made some new sequences : 

 

fic(n)=∑ni=1fib(i)fic(n)=∑i=1nfib(i)

fid(n)=∑ni=1fic(i)fid(n)=∑i=1nfic(i)

 

fib(i) means the ith element in the Fibonacci sequence :

 fib(1)=fib(2)=1,fib(i)=fib(i−1)+fib(i−2),i≥3fib(1)=fib(2)=1,fib(i)=fib(i−1)+fib(i−2),i≥3

 

At first this problem is to calculate fid(n), but that is too easy. So after discussing with 10256, they changed the problem:

Given a positive integer array a1,a2,...,ana1,a2,...,an, perform the following two types of operations:

 

1. Given l,r,x, for all l≤i≤rl≤i≤r, execute ai=ai+xai=ai+x. 

2. Given l,r, calculate(∑ri=lfid(ai))%100000007(∑i=lrfid(ai))%100000007. 

输入描述:

 

The first line of the input contains an integer n, indicating the length of the array.

The second line contains n positive integers separated by spaces, indicating a1,a2,...,an−1,ana1,a2,...,an−1,an.

The third line contains an integer Q, indicating the number of operations.

For the next Q lines, it is either 1 l r x1 l r x, indicating the first type of operation, or 2 l r2 l r, indicating the second type of operation.

All values in input are integers.

1≤n,Q≤100000,1≤ai,x≤109,1≤l≤r≤n.1≤n,Q≤100000,1≤ai,x≤109,1≤l≤r≤n.

输出描述:

 

For each operation of second type, output(∑ri=lfid(ai))%100000007(∑i=lrfid(ai))%100000007.

示例1

输入

复制

3
1 2 3
6
2 1 3
1 1 3 1
2 1 3
1 1 1 2
1 2 2 3
2 1 3

输出

复制

11
24
74

 注意取模是1e8+7...很坑

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int mod=1e8+7;
int n,q;
struct matrix
{
	ll a[4][4];
	matrix(){memset(a,0,sizeof a);}
	void init()
	{
		memset(a,0,sizeof a);
		for(int i=0;i<4;i++)a[i][i]=1;
	}
    void solve(){a[0][0]=a[0][1]=a[1][0]=a[2][0]=a[2][2]=a[3][2]=a[3][3]=1;}
    matrix operator *(const matrix &b)const
	{
		matrix res;
		for(int i=0;i<4;i++)
			for(int j=0;j<4;j++)
				for(int k=0;k<4;k++)
					res.a[i][j]=(res.a[i][j]+a[i][k]*b.a[k][j])%mod;
		return res;
	}
	matrix operator +(const matrix &b)const
	{
		matrix res;
		for(int i=0;i<4;i++)
			for(int j=0;j<4;j++)
	  		    res.a[i][j]=(a[i][j]+b.a[i][j])%mod;
		return res;
	}
}d[maxn<<2],b[maxn<<2],base;
void build(int l,int r,int p)
{
	b[p].init();
	if(l==r) {d[p].init();return ;}
	int m=(l+r)>>1;build(l,m,p<<1);build(m+1,r,p<<1|1);
	d[p]=d[p<<1]+d[p<<1|1];
}
void update(int l,int r,int s,int t,int p,matrix c)
{
	if(l==s&&t==r){d[p]=d[p]*c,b[p]=b[p]*c;return;}
	int m=(s+t)>>1;
	if(r<=m)update(l,r,s,m,p<<1,c);
	else if(m<l)update(l,r,m+1,t,p<<1|1,c);
	else update(l,m,s,m,p<<1,c),update(m+1,r,m+1,t,p<<1|1,c);
	d[p]=(d[p<<1]+d[p<<1|1])*b[p];
}
matrix query(int l,int r,int s,int t,int p)
{
	if(l==s&&t==r)return d[p];
	int m=(s+t)>>1;
	if(r<=m) return query(l,r,s,m,p<<1)*b[p];
	else if(m<l) return query(l,r,m+1,t,p<<1|1)*b[p];
	else return b[p]*(query(l,m,s,m,p<<1)+query(m+1,r,m+1,t,p<<1|1));
}
matrix fpow(matrix a,ll b)
{
	matrix res;res.init();
	while(b)
	{
		if(b&1)res=res*a;
		a=a*a;
		b>>=1;
	}
	return res;
}
int main()
{
	matrix base;base.solve();
	scanf("%d",&n);build(1,n,1);
	for(int i=1;i<=n;i++){int x;scanf("%d",&x);update(i,i,1,n,1,fpow(base,x+2));}
	scanf("%d",&q);
    while(q--)
    {
    	int p;scanf("%d",&p);
    	if(p==1){int l,r,x; scanf("%d%d%d",&l,&r,&x),update(l,r,1,n,1,fpow(base,x));}
    	if(p==2){int l,r;scanf("%d%d",&l,&r),printf("%lld\n",query(l,r,1,n,1).a[3][1]);}
    }
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值