您的位置:首页 > 其它

【NOIP2016提高A组模拟7.15】斐波那契数列(矩阵乘法)

2017-09-18 19:50 381 查看

题目



数据



小结

30%做法不知道怎么做出来的~暴力都能60吧。

60%暴力咯~

100%

然后就是比较恶心的一个东西:叫做“矩阵乘法”。

这东西大家应该不用理解太久,连我这个蒟蒻都只是理解了半个小时~

不讲废话:

我们的斐波那契数列是这样的:

0 1 1 2 3 5 8 13…….

我们一个矩阵,只有两个数,就是我们当前的这个以及前一个,这样就可以推出下一个了。

推一推:



发现,答案的第一位就是原始数的第二位,那么原始数的第一位对答案的第一位是没有贡献的,所以:



我们考虑后面,第二位是前面两位之和,那么就两个都有贡献咯~



这样这个矩阵就推出来啦,我们就可以用快速幂的思想去做,其实就是乘这个矩阵n-1次。

#include<cstdio>
#include<iostream>
using namespace std;
long long n,m;
long long a[3],b[3,3],c[3],d[3,3];
void ksm(long long n,long long p)
{
int i,j,k;
while(n)
{
if(n&1)
{
c[1]=0;c[2]=0;
for (i=1;i<=2;++i)
for (j=1;j<=2;++j)
(c[i]+=a[j]*b[j,i])%=p;
a[1]=c[1];a[2]=c[2];
}
n>>=1;
d[1,1]=0;d[1,2]=0;
d[2,1]=0;d[2,2]=0;
for (i=1;i<=2;++i)
for (j=1;j<=2;++j)
for (k=1;k<=2;++k)
(d[i,j]+=b[i,k]*b[k,j])%=p;
b[1,1]=d[1,1];b[1,2]=d[1,2];
b[2,1]=d[2,1];b[2,2]=d[2,2];
}
}
int main()
{
scanf("%lld%lld",&n,&m);
b[1,1]=0;
b[1,2]=1;
b[2,1]=1;
b[2,2]=1;
a[1]=1;
a[2]=1;
ksm(n-1,m);
printf("%lld\n",a[2]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: