题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1588
题目大意:先要知道一组斐波那契数列
| i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| f(i) | 0 | 1 | 1 | 2 | 3 | 5 | 8 | 13 |
现在知道一组公式g(i)=k*i+b;(i=0,1,2,3...n-1)
让你求出 f(g(i)) 的总和(i=01,2,3,...,n-1),比如给出的数据是2 1 4 100
2*0+1=1 f(1)=1
2*1+1=3 f(3)=2
2*2+1=5 f(5)=5
2*3+1=7 f(7)=13
故sum=21%100
没有什么思路做这个题目。
后来看了题解发现数列的乘法可以构造出矩阵相乘。
fibonacci数列满足 |F(n+1) F(n) |= |1 1|^n
|F(n) F(n-1)| |1 0|
#include<stdio.h>
#include<string.h>
#define N 2
struct Matrix
{
__int64 a[N][N];
}res,tmp,ans,B,C,S,AB,AK;
Matrix A={1,1,1,0}; //初始化矩阵A
Matrix S0={1,0,0,1}; //(A^k)^0
int m;
Matrix mul(Matrix x,Matrix y) //矩阵乘法
{
memset(tmp.a,0,sizeof(tmp.a));
int i,j,k;
for(i=0;i<2;i++)
for(j=0;j<2;j++)
for(k=0;k<2;k++)
{
tmp.a[i][j]+=(x.a[i][k]*y.a[k][j]);
tmp.a[i][j]%=m;
}
return tmp;
}
Matrix quickpow(Matrix origin,int k) //矩阵快速幂
{
int i;
memset(res.a,0,sizeof(res.a));
for(i=0;i<2;i++)
res.a[i][i]=1;
while(k)
{
if(k&1)
res=mul(res,origin);
origin=mul(origin,origin);
k>>=1;
}
return res;
}
Matrix add(Matrix x,Matrix y) //矩阵加法
{
int i,j;
for(i=0;i<2;i++)
for(j=0;j<2;j++)
tmp.a[i][j]=(x.a[i][j]+y.a[i][j])%m;
return tmp;
}
Matrix bin(int n) //二分
{
if(n<=1)
return AK;
else if(n%2)
{
B=bin(n-1);
C=quickpow(AK,n);
return add(B,C);
}
else
{
B=bin(n/2);
C=quickpow(AK,n/2);
C=mul(B,C);
return add(B,C);
}
}
void print(Matrix x)
{
int i,j;
for(i=0;i<2;i++)
{
for(j=0;j<2;j++)
printf("%d ",x.a[i][j]);
printf("\n");
}
}
int main()
{
int k,b,n;
while(scanf("%d%d%d%d",&k,&b,&n,&m)!=EOF)
{
//fibonacci数列满足 |F(n+1) F(n) |= |1 1|^n
// |F(n) F(n-1)| |1 0|
AB=quickpow(A,b); //A^b
// print(AB);
AK=quickpow(A,k); //A^k
// print(AK);
S=bin(n-1); //F(n-1)
S=add(S0,S);
// print(S);
ans=mul(AB,S);
printf("%d\n",ans.a[0][1]);
}
return 0;
}
矩阵十题【三】 HDU 1588 Gauss Fibonacci,布布扣,bubuko.com
矩阵十题【三】 HDU 1588 Gauss Fibonacci
原文地址:http://blog.csdn.net/u010468553/article/details/38424973