HDU 2855 (矩阵快速幂)

时间:2023-03-08 15:53:06
HDU 2855 (矩阵快速幂)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2855

题目大意:求$S(n)=\sum_{k=0}^{n}C_{n}^{k}Fibonacci(k)$

解题思路

题目挺吓人的。先把完整组合数+Fibonacci展开来。

利用Fibonacci的特性,从第一项开始消啊消,消到只有一个数:

$S(0)=f(0)$

$S(1)=f(2)$

$S(2)=f(4)$

$S(n)=f(2*n)$

这样矩阵快速幂就可以了,特判$n=0$时的情况。

快速幂矩阵

$\begin{bmatrix}f1 & f0 \\ 0 & 0\end{bmatrix}\begin{bmatrix}1 & 1 \\1 & 0 \end{bmatrix}=\begin{bmatrix}f2 & f1 \\
0 & 0\end{bmatrix}$

代码

#include "cstdio"
#include "cstring"
#define LL long long
#define mod m
#define K 2
LL n,m;
struct Matrix
{
LL mat[K][K];
Matrix() {memset(mat,,sizeof(mat));}
Matrix(LL *val)
{
int idx=;
for(int i=;i<K;i++)
for(int j=;j<K;j++)
mat[i][j]=val[idx++];
}
};
Matrix operator * (Matrix a,Matrix b)
{
Matrix ret;
for(int i=;i<K;i++)
for(int j=;j<K;j++)
{
ret.mat[i][j]=;
for(int k=;k<K;k++)
ret.mat[i][j]+=((a.mat[i][k]*b.mat[k][j])%mod);
}
return ret;
}
Matrix operator ^ (Matrix a,LL n)
{
Matrix ret,base=a;
for(int i=;i<K;i++) ret.mat[i][i]=;
while(n)
{
if(n&) ret=ret*base;
base=base*base;
n>>=;
}
return ret;
}
int main()
{
//freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%I64d%I64d",&n,&m);
if(n==) printf("0\n");
else
{
LL obj=n*;
LL bval[]={,,,};
LL pval[]={,,,};
Matrix Base(bval),Pow(pval),ans=Pow^(obj-);
ans=Base*ans;
printf("%I64d\n",ans.mat[][]%mod);
}
}
}