21山东省赛热身赛B(Fib[i]/(2^i))(矩阵快速幂)

题目

点这里
在这里插入图片描述

算法思路

  1. 公式推不出来,只能推矩阵了
  2. 因为 F ( i ) = F ( i − 1 ) + F ( i − 2 ) F(i)=F(i-1)+F(i-2) F(i)=F(i1)+F(i2),设原来的数列为f(i),则 f ( i ) ∗ 8 = f ( i − 1 ) ∗ 4 + f ( i − 2 ) ∗ 2 f(i)*8=f(i-1)*4+f(i-2)*2 f(i)8=f(i1)4+f(i2)2,即 f ( i ) = f ( i − 1 ) 2 + f ( i − 2 ) 4 f(i)=\cfrac{f(i-1)}{2}+\cfrac{f(i-2)}{4} f(i)=2f(i1)+4f(i2)
  3. 因为题目要求解的是 s u m ( i ) sum(i) sum(i),显然 s u m ( i ) = s u m ( i − 1 ) + f ( i ) sum(i)=sum(i-1)+f(i) sum(i)=sum(i1)+f(i)
  4. 这个时候我们就可以设立初始矩阵的状态,和操作矩阵了,设立 [ f ( x ) , f ( x − 1 ) , s u m ( x − 1 ) ] T [f(x),f(x-1),sum(x-1)]^{T} [f(x),f(x1),sum(x1)]T为所求矩阵(列向量),下一状态为 [ f ( x + 1 ) , f ( x ) , s u m ( x ) ] T [f(x+1),f(x),sum(x)]^{T} [f(x+1),f(x),sum(x)]T
  5. f ( x + 1 ) = f ( x ) 2 + f ( x − 1 ) 4 f(x+1)=\cfrac{f(x)}{2}+\cfrac{f(x-1)}{4} f(x+1)=2f(x)+4f(x1)得,操作矩阵的第一列为 [ 1 2 , 1 4 , 0 ] T [\cfrac{1}{2},\cfrac{1}{4},0]^T [21,41,0]T
  6. f ( x ) = f ( x ) f(x)=f(x) f(x)=f(x)得到操作矩阵第二列为 [ 1 , 0 , 0 ] [1,0,0] [1,0,0]
  7. s u m ( x ) = s u m ( x − 1 ) + f ( x ) sum(x)=sum(x-1)+f(x) sum(x)=sum(x1)+f(x)得到操作矩阵第三列为 [ 1 , 0 , 1 ] [1,0,1] [1,0,1]
  8. 最终这样我们就得出了操作矩阵,然后我们用矩阵快速幂算出 A n − 1 A^{n-1} An1(的第三列),再乘以初始矩阵 [ f ( 2 ) , f ( 1 ) , s u m ( 1 ) ] T = [ 0.25 , 0.5 , 0.5 ] T [f(2),f(1),sum(1)]^T=[0.25,0.5,0.5]^T [f(2),f(1),sum(1)]T=[0.25,0.5,0.5]T,则得到最终的答案矩阵s,s[3]即为所求答案

代码实现

(队友写的,以后还是写结构体好一点,不然最后一行,每次迷迷糊糊)

#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
using namespace std;
#define el '\n'
#define cl putchar('\n')
#define pb push_back
#define eb emplace_back
#define fir first
#define sec second


typedef long long ll;
typedef pair<int,int> pii;
typedef vector<int> vci;
typedef map<int,int> mii;
typedef mii::iterator mii_it;

const int N=1e5+10,M=1e3+10;

double a[5][5],b[5][5],ans[5][5];

void chenans() {
	for(int i=1; i<=3; i++) {
		for(int j=1; j<=3; j++)b[i][j]=ans[i][j];
	}
	for(int i=1; i<=3; i++) {
		for(int j=1; j<=3; j++) {
			ans[i][j]=0;
			for(int k=1; k<=3; k++) {
                ans[i][j]+=b[i][k]*a[k][j];
			}
		}
	}
}
void chena() {
	for(int i=1; i<=3; i++) {
		for(int j=1; j<=3; j++)b[i][j]=a[i][j];
	}
	for(int i=1; i<=3; i++) {
		for(int j=1; j<=3; j++) {
			a[i][j]=0;
			for(int k=1; k<=3; k++) {
                a[i][j]+=b[i][k]*b[k][j];
			}
		}
	}
}
void ksm(int b) {
	for(int i=1; i<=3; i++)ans[i][i]=1;
	a[1][1]=0.5;
	a[2][1]=0.25;
	a[1][2]=1;
	a[1][3]=1;
	a[3][3]=1;
	while(b) {
		if(b&1)chenans();
		b=b/2;
		chena();
	}
}

int main() {
	cin.tie(0);
	cout.tie(0);
	
	int n;
	cin>>n;
	ksm(n-1);
//	for(int i=1;i<=3;i++){
//		for(int j=1;j<=3;j++){
//			printf("%.6f ",ans[i][j]);
//		}
//		cl;
//	} 
	printf("%.8f",ans[1][3]*0.25+ans[2][3]*0.5+ans[3][3]*0.5);

//	cin>>T;
//	while(T--) {
//
//	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值