Sum of Tribonacci Numbers(前缀和,矩阵快速幂)

本文介绍了一种计算Tribonacci数列中从a到b范围内和的算法,使用矩阵乘法技巧,特别注意了当和可能为负时对1,000,000,007取模的处理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

该题目需要注意的是会出现两个前缀和相减出现负数的情况,如下:

所以需要在两前缀和相减取模之前先加上一个M

题目描述

Everybody knows Fibonacci numbers, now we are talking about the Tribonacci numbers:
T[0] = T[1] = T[2] = 1;
T[n] = T[n - 1] + T[n - 2] + T[n - 3] (n >= 3)

Given a and b, you are asked to calculate the sum from the ath Fibonacci number to the bth Fibonacci number, mod 1,000,000,007, that is (T[a] + T[a + 1] + ... + T[b]) % 1,000,000,007.

输入

There are multiple cases (no more than 100).

Each case contain two non-negative integers a b(a <= b and a, b < 1,000,000,000)

输出

For each case, output the sum % 1,000,000,007.

样例输入 Copy
0 2
0 5

以下为AC代码

#include<bits/stdc++.h>
using namespace std;
int a1[5][5];
int ans[5][5];
const int M=1000000007;
void matrixmul(int m1[][5],int m2[][5],int col)
{
	int b[5][5];
	memset(b,0,sizeof(b));
	for(int i=1;i<=4;i++)
		for(int j=1;j<=col;j++)
			for(int p=1;p<=4;p++){
				b[i][j]+=((long long)m1[i][p]*(long long)m2[p][j])%M;
				b[i][j]%=M;
			}
	for(int i=1;i<=4;i++)
		for(int j=1;j<=col;j++)m2[i][j]=b[i][j]%M;
}
int main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int a,b,sum1,sum2;
	while(cin>>a>>b){
		int a2[5][5]={
			0,0,0,0,0,
			0,1,1,1,1,
			0,0,1,1,1,
			0,0,1,0,0,
			0,0,0,1,0	
		};
		a1[1][1]=3,a1[2][1]=1,a1[3][1]=1,a1[4][1]=1;
		for(int i=1;i<=4;i++)
			for(int j=1;j<=4;j++)ans[i][j]=(i==j);
		int b1=b;
		if(b<=2){
			cout<<b-a+1<<'\n';
			continue;
		}
		b-=(a-1);
		a-=3;
		if(a<=0){
			switch(a){
				case -3:sum1=0;break;
				case -2:sum1=1;break;
				case -1:sum1=2;break;
				case 0:sum1=3;break;
			}
			b=b1-2;
			goto EXIT;
		}
		while(a){
			if(a%2){
				a--;
				matrixmul(a2,ans,4);
			}else{
				a/=2;
				matrixmul(a2,a2,4);
			}
		}
		matrixmul(ans,a1,1);
		sum1=a1[1][1]%M;
		EXIT:
		int b2[5][5]={
			0,0,0,0,0,
			0,1,1,1,1,
			0,0,1,1,1,
			0,0,1,0,0,
			0,0,0,1,0	
		};
		for(int i=1;i<=4;i++)
			for(int j=1;j<=4;j++)ans[i][j]=(i==j);
		while(b){
			if(b%2){
				b--;
				matrixmul(b2,ans,4);
			}else{
				b/=2;
				matrixmul(b2,b2,4);
			}
		}
		matrixmul(ans,a1,1);
		sum2=a1[1][1]%M;
		cout<<(sum2+M-sum1)%M<<'\n';//加上M以避免出现负数情况
	}
	return 0;
}
样例输出 Copy
3
20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值