题目:
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