题目:
2 1 4 100 2 0 4 100
21 12
题意:给一个函数g(i)=k*i+b,求f(g(0))+f(g(1))+....+f(g(n-1)),f是斐波拉契数列。
思路:由矩阵快速幂可以求得某个斐波拉契项的值,但每项都求出来复杂度是NlogN,N<=10^9,所以不可取,由于f(k*i+b)=A^(k*i+b),A是递推矩阵也就是[(1,1),(1,0)],提取因子就得到A^b((A^k)*0+(A^k)+(A^k)^2+...+(A^k)^(n-1)),而矩阵的等比求和可以二分递推来求,假设当前有6个矩阵,那么A^1+A^2+...+A^6=A^1+A^2+A^3+A^3(A^1+A^2+A^3)=(A^1+A^2+A^3)(I+A^3),可以参见matrix67的博客,也可以看代码。
代码:
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include<climits>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <list>
#include <stdexcept>
#include <functional>
#include <utility>
#include <ctime>
using namespace std;
#define PB push_back
#define MP make_pair
#define REP(i,x,n) for(int i=x;i<(n);++i)
#define FOR(i,l,h) for(int i=(l);i<=(h);++i)
#define FORD(i,h,l) for(int i=(h);i>=(l);--i)
#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define RI(X) scanf("%d", &(X))
#define RII(X, Y) scanf("%d%d", &(X), &(Y))
#define RIII(X, Y, Z) scanf("%d%d%d", &(X), &(Y), &(Z))
#define DRI(X) int (X); scanf("%d", &X)
#define DRII(X, Y) int X, Y; scanf("%d%d", &X, &Y)
#define DRIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)
#define OI(X) printf("%d",X);
#define RS(X) scanf("%s", (X))
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define F first
#define S second
#define Swap(a, b) (a ^= b, b ^= a, a ^= b)
#define Dpoint strcut node{int x,y}
#define cmpd int cmp(const int &a,const int &b){return a>b;}
/*#ifdef HOME
freopen("in.txt","r",stdin);
#endif*/
const int MOD = 1e9+7;
typedef vector<int> VI;
typedef vector<string> VS;
typedef vector<double> VD;
typedef long long LL;
typedef pair<int,int> PII;
//#define HOME
int Scan()
{
int res = 0, ch, flag = 0;
if((ch = getchar()) == '-') //判断正负
flag = 1;
else if(ch >= '0' && ch <= '9') //得到完整的数
res = ch - '0';
while((ch = getchar()) >= '0' && ch <= '9' )
res = res * 10 + ch - '0';
return flag ? -res : res;
}
/*----------------PLEASE-----DO-----NOT-----HACK-----ME--------------------*/
int k,b,n,M;
struct Matrix
{
int m[5][5];
void init()
{
MS0(m);
}
void print()
{
printf("%d %d\n%d %d\n",m[0][0],m[0][1],m[1][0],m[1][1]);
}
};
Matrix I;
Matrix mul(Matrix a,Matrix b)
{
Matrix c;
c.init();
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
{
c.m[i][j]=(c.m[i][j]+(long long)a.m[i][k]*b.m[k][j])%M;
}
return c;
}
Matrix mypow(Matrix a,int k)
{
Matrix ans;
ans.init();
for(int i=0;i<2;i++)
ans.m[i][i]=1;
Matrix temp=a;
while(k)
{
if(k&1)
ans=mul(ans,temp);
k>>=1;
temp=mul(temp,temp);
}
return ans;
}
Matrix add(Matrix a,Matrix b)
{
Matrix ans;
ans.init();
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
ans.m[i][j]=(a.m[i][j]+b.m[i][j])%M;
return ans;
}
Matrix solve(Matrix a,int k)
{
if(k==0)
{
Matrix b;
b.init();
return b;
}
if(k==1)
return a;
if(k&1)
return add(solve(a,k-1),mypow(a,k));
else
return mul(solve(a,k>>1),add(I,mypow(a,k>>1)));
}
int main()
{
I.init();
for(int i=0;i<2;i++)
I.m[i][i]=1;
while(scanf("%d%d%d%d",&k,&b,&n,&M)!=EOF)
{
if(n==0)
{printf("0\n");
continue;}
Matrix A;
A.init();
A.m[0][0]=A.m[1][0]=A.m[0][1]=1;
A.m[1][1]=0;
Matrix B=mypow(A,b);
Matrix C=mypow(A,k);
//C.print();
Matrix D=solve(C,n-1);
//D.print();
Matrix E=add(I,D);
//E.print();
Matrix F=mul(B,E);
//F.print();
//H.print();
int ans=F.m[1][0];
printf("%d\n",ans);
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
hdu1588 Gauss Fibonacci(矩阵快速幂+二分求矩阵等比和)
原文地址:http://blog.csdn.net/u013840081/article/details/48040573