习题:M斐波那契数列(矩阵优化)

题目

传送门

思路

首先可以很容易的发现

\(f(n)=a^x*b^y\)

之后我们根据函数的定义单独考虑\(f(n)\)是a的多少次幂乘上b的多少次幂

然后我们很容易的发现,

\(f(n)\)这个函数其实就是对指数进行了\(g_n=g_{n-1}+g_{n-2}\)

也就是斐波拉契数列

之后可以自然而然地想到矩阵的优化

但是这里要注意,虽然a和b的加速矩阵是一样的

但是他们的初始矩阵却是不一样的

因为\(f(0)==a\)\(f(1)==b\)的情况

另外当mod是质数的时候,\(\varphi(mod)=mod-1\)

而且进行矩阵快速幂的时候的模数与最后算答案的模数是不一样的

代码

#include<iostream>
#include<cstring>
using namespace std;
const long long mod=1e9+6;
const long long modd=1e9+7;
struct mat
{
	long long n;
	long long m;
	long long a[5][5];
	mat()
	{
		n=0;
		m=0;
		memset(a,0,sizeof(a));
	}
	friend mat operator * (const mat &a,const mat &b) 
	{
		mat t;
		t.n=a.n;
		t.m=b.m;
		for(int i=1;i<=a.n;i++)
		{
			for(int j=1;j<=b.m;j++)
			{
				for(int k=1;k<=a.m;k++)
				{
					t.a[i][j]=(t.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
				}
			}
		}
		return t;
	}
};
long long varphi(long long n)
{
	long long ans=n;
	for(int i=2;1ll*i*i<=n;i++)
	{
		if(n%i==0)
		{
			ans=ans/i*(i-1);
			while(!(n%i))
				n/=i;
		}
	}
	if(n>1)
		ans=ans/n*(n-1);
	return ans;
}
mat qkpow(mat a,long long b)
{
	if(b==1)
		return a;
	mat t=qkpow(a,b/2);
	t=(t*t);
	if(b%2==1)
		t=(t*a);
	return t;
}
long long qkpow(long long a,long long b)
{
	if(b==0)
		return 1;
	if(b==1)
		return a;
	long long t=qkpow(a,b/2);
	t=(t*t)%modd;
	if(b%2==1)
		t=(t*a)%modd;
	return t;
}
long long a,b,n;
mat t1;
mat t2;
mat acc;
void init()
{
	acc.n=acc.m=4;
	acc.a[1][2]=acc.a[2][1]=acc.a[2][2]=1;
	acc.a[1][1]=0;
}
int main()
{
	while(cin>>a>>b>>n)
	{
		if(n==0)
		{
			cout<<a<<'\n';
			continue;
		}
		if(n==1)
		{
			cout<<b<<'\n';
			continue;
		}
		t1.n=t2.n=1;
		t1.m=t2.m=2;
		t1.a[1][1]=t2.a[1][2]=1;
		t1.a[1][2]=t2.a[1][1]=0;
		init();
		t1=t1*qkpow(acc,n-1);
		init();
		t2=t2*qkpow(acc,n-1);
		//cout<<t1.a[1][2]<<' '<<t2.a[1][2]<<'\n';
		cout<<qkpow(a%modd,t1.a[1][2])*qkpow(b%modd,t2.a[1][2])%modd<<'\n';
	}
	return 0;
}
posted @ 2019-11-24 15:28  loney_s  阅读(249)  评论(0)    收藏  举报