[c]sdnuoj1085 用矩阵做爬楼梯

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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值