LOJ #10221. 「一本通 6.5 例 3」Fibonacci 前 n 项和

思路
因为:
s[n]=1*s[n-1]+1*f[n]+0*f[n-1]
f[n+1]=0*s[n-1]+1*f[n]+1*f[n-1]
f[n]=0*s[n-1]+1*f[n]+0*f[n-1]
转成矩阵:
𝒔[𝒏]     𝟏 𝟏 𝟎    𝒔[𝒏 − 𝟏]
𝒇[𝒏 + 𝟏] =   𝟎 𝟏 𝟏      *    𝒇[𝒏]
𝒇[𝒏]     𝟎 𝟏 𝟎   𝒇[𝒏 − 𝟏]
所以:
𝒔[𝒏]       𝟏 𝟏 𝟎   ^  𝒏−𝟏    𝒔[𝟏]
𝒇[𝒏 + 𝟏]    =     𝟎 𝟏 𝟏     *      𝒇[𝟐]
𝒇[𝒏]       𝟎 𝟏 𝟎          𝒇[𝟏]

代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

long long n,Mod;

struct no {
	long long a[5][5];
} ans,x;

no mul(no &x,no &y) {
	no c;
	memset(&c,0,sizeof(c));
	for(int i=1; i<=3; i++)
		for(int j=1; j<=3; j++)
			for(int k=1; k<=3; k++)
				c.a[i][j]=(c.a[i][j]+x.a[i][k]*y.a[k][j]%Mod);
	return c;
}

void work(long long n) {
	while(n) {
		if(n&1)
			ans=mul(ans,x);
		x=mul(x,x);
		n>>=1;
	}
}

int main () {
	ans.a[1][1]=ans.a[2][2]=ans.a[3][3]=1;
	x.a[1][1]=1;
	x.a[1][2]=1;
	x.a[1][3]=0;
	x.a[2][1]=0;
	x.a[2][2]=1;
	x.a[2][3]=1;
	x.a[3][1]=0;
	x.a[3][2]=1;
	x.a[3][3]=0;
	scanf("%lld%lld",&n,&Mod);
	work(n-1);
	printf("%lld\n",(ans.a[1][1]+ans.a[1][2]+ans.a[1][3])%Mod);
	return 0;
}

 

posted @ 2019-08-10 02:05  双子最可爱啦  阅读(242)  评论(0编辑  收藏  举报