题目描述:
Q老师 对数列有一种非同一般的热爱,尤其是优美的斐波那契数列。
这一天,Q老师 为了增强大家对于斐波那契数列的理解,决定在斐波那契的基础上创建一个新的数列 f(x) 来考一考大家。数列 f(x) 定义如下:
当 x < 10 时,f(x) = x;
当 x ≥ 10 时,f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10),ai 只能为 0 或 1。
Q老师 将给定 a0~a9,以及两个正整数 k m,询问 f(k) % m 的数值大小。
聪明的你能通过 Q老师 的考验吗?
input:
输出文件包含多组测试用例,每组测试用例格式如下:
第一行给定两个正整数 k m。(k < 2e9, m < 1e5)
第二行给定十个整数,分别表示 a0~a9。
output:
对于每一组测试用例输出一行,表示 f(k) % m 的数值大小。
思路:
根据递推公式,构造快速幂矩阵,通过计算,最终的答案向量将是快速幂矩阵的k-9次方乘初始向量a9 a8 ...a0
快速幂矩阵及其乘法运算通过结构体的方式进行了封装并重载*运算符。
最终结果如下:
时间复杂度:log(k)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int k,m,a[11];
struct node
{
long long n[11][11];
node operator *(const node &t)
{
node ans;
for(int i=1;i<=10;i++)
for(int j=1;j<=10;j++)
for(int k=1;k<=10;k++)
ans.n[i][j]=(ans.n[i][j]+((n[i][k]%m)*(t.n[k][j]%m))%m)%m;
return ans;
}
node(){memset(n,0,sizeof(n));}
node(int*t)
{
memset(n,0,sizeof(n));
for(int i=1;i<=10;i++)
n[1][i]=t[i];
for(int i=2;i<=10;i++)
n[i][i-1]=1;
}
};
int main()
{
while(scanf("%d%d",&k,&m)!=EOF)
{
for(int i=1;i<=10;i++)
cin>>a[i];
node t(a);
node ans;
for(int i=1;i<=10;i++)
ans.n[i][i]=1;
if(k<10)
{
cout<<k<<endl;
continue;
}
k-=9;
while(k)
{
if(k&1) ans=ans*t;
t=t*t;
k>>=1;
}
long long fina=0;
for(int i=1;i<=10;i++)
fina=(fina+ans.n[1][i]*(10-i))%m;
cout<<fina<<endl;
}
return 0;
}