http://www.acmicpc.sdnu.edu.cn/problem/show/1085
题目标题:爬楼梯再加强版(名字真中二)
题目大意:爬楼梯的问题上升到n取到相当大的时候
这个题不能再用递归或循环来做了,那样必定超时,可以用矩阵的做法节约时间,我先把2的20次方之内算出来了,这种方法非常不可取,应该在程序里算到2的64次方,而我是一开始傻了后来又懒得改、、、于是就这样了
#include<stdio.h>
#include<math.h>
#include<iostream>
using namespace std;
long long a[21][3][3]={
{{1,1,1},{1,0,0},{0,1,0}},
{{2,2,1},{1,1,1},{1,0,0}},
{{7,6,4},{4,3,2},{2,2,1}},
{{81,68,44},{44,37,24},{24,20,13}},
{{10609,8904,5768},{5768,4841,3136},{3136,2632,1705}},
{{181997601,152748176,98950096},{98950096,83047505,53798080},{53798080,45152016,29249425}},
{{254469491,502349528,890873279},{890873279,363596219,611476256},{611476256,279397023,752119970}},
{{877398423,798586812,885290616},{885290616,992107814,913296203},{913296203,971994420,78811611}},
{{554780554,176085328,159625346},{159625346,395155208,16459982},{16459982,143165364,378695226}},
{{456358172,663557897,631130698},{631130698,825227481,32427199},{32427199,598703499,792800282}},
{{54616240,351099040,290364440},{290364440,764251807,60734600},{60734600,229629840,703517207}},
{{65545761,608003626,847996723},{847996723,217549045,760006910},{760006910,87989813,457542142}},
{{191989819,903985182,310351083},{310351083,881638743,593634099},{593634099,716716991,288004644}},
{{868149120,30472158,652751872},{652751872,215397248,377720293},{377720293,275031579,837676962}},
{{942373761,689570428,905090014},{905090014,37283747,784480421},{784480421,120609593,252803333}},
{{423888056,808940073,48648117},{48648117,375239939,760291956},{760291956,288356168,614947990}},
{{574249674,586856825,238601869},{238601869,335647805,348254956},{348254956,890346920,987392856}},
{{889450251,546911802,97656930},{97656930,791793321,449254872},{449254872,648402065,342538449}},
{{936283574,757306901,277385183},{277385183,658898391,479921718},{479921718,797463472,178976673}},
{{297655090,557047884,978263282},{978263282,319391815,578784609},{578784609,399478673,740607213}},
{{609137764,355343911,478143462},{478143462,130994302,877200456},{877200456,600943013,253793853}},
};
long long plt(long long x){
long long re[3][3]={{1,1,1},{1,0,0},{0,1,0}};
long long q=x;
if(x==0) return 0;
if(x==1) return 1;
else if(x==2) return 2;
else if(x==3) return 4;
else {
q-=3;
long long c[3][3];
for(;q>=1048576;q=q-1048576){
c[0][0]=(re[0][0]*a[20][0][0]+re[1][0]*a[20][0][1]+re[2][0]*a[20][0][2])%1000000007;
c[1][0]=(re[0][0]*a[20][1][0]+re[1][0]*a[20][1][1]+re[2][0]*a[20][1][2])%1000000007;
c[2][0]=(re[0][0]*a[20][2][0]+re[1][0]*a[20][2][1]+re[2][0]*a[20][2][2])%1000000007;
c[0][1]=(re[0][1]*a[20][0][0]+re[1][1]*a[20][0][1]+re[2][1]*a[20][0][2])%1000000007;
c[1][1]=(re[0][1]*a[20][1][0]+re[1][1]*a[20][1][1]+re[2][1]*a[20][1][2])%1000000007;
c[2][1]=(re[0][1]*a[20][2][0]+re[1][1]*a[20][2][1]+re[2][1]*a[20][2][2])%1000000007;
c[0][2]=(re[0][2]*a[20][0][0]+re[1][2]*a[20][0][1]+re[2][2]*a[20][0][2])%1000000007;
c[1][2]=(re[0][2]*a[20][1][0]+re[1][2]*a[20][1][1]+re[2][2]*a[20][1][2])%1000000007;
c[2][2]=(re[0][2]*a[20][2][0]+re[1][2]*a[20][2][1]+re[2][2]*a[20][2][2])%1000000007;
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
re[i][j]=c[i][j];
}
}
}
int s=19;
while(s!=-1){
if(q>=pow(2,s)){
c[0][0]=(re[0][0]*a[s][0][0]+re[1][0]*a[s][0][1]+re[2][0]*a[s][0][2])%1000000007;
c[1][0]=(re[0][0]*a[s][1][0]+re[1][0]*a[s][1][1]+re[2][0]*a[s][1][2])%1000000007;
c[2][0]=(re[0][0]*a[s][2][0]+re[1][0]*a[s][2][1]+re[2][0]*a[s][2][2])%1000000007;
c[0][1]=(re[0][1]*a[s][0][0]+re[1][1]*a[s][0][1]+re[2][1]*a[s][0][2])%1000000007;
c[1][1]=(re[0][1]*a[s][1][0]+re[1][1]*a[s][1][1]+re[2][1]*a[s][1][2])%1000000007;
c[2][1]=(re[0][1]*a[s][2][0]+re[1][1]*a[s][2][1]+re[2][1]*a[s][2][2])%1000000007;
c[0][2]=(re[0][2]*a[s][0][0]+re[1][2]*a[s][0][1]+re[2][2]*a[s][0][2])%1000000007;
c[1][2]=(re[0][2]*a[s][1][0]+re[1][2]*a[s][1][1]+re[2][2]*a[s][1][2])%1000000007;
c[2][2]=(re[0][2]*a[s][2][0]+re[1][2]*a[s][2][1]+re[2][2]*a[s][2][2])%1000000007;
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
re[i][j]=c[i][j];
}
}
q-=pow(2,s);
}
s--;
}
return (re[0][0]*2+re[0][1]+re[0][2])%1000000007;
}
}
int main(){
long long n;
while(cin>>n){
long long x=plt(n);
cout<<x<<endl;
}
return 0;
}