在hihoCoder上遇到一道骨牌覆盖问题,分析后发现其实就是Fibonacii,但是要求高效的时间复杂度,也就是说传统递归方法实现是不能满足要求的。但是如果用快速幂方法求解的话,非常适用。
时间限制:
10000ms
单点时限:
1000ms
内存限制:
256MB
-
62247088
样例输出
-
17748018
描述
骨牌,一种古老的玩具。今天我们要研究的是骨牌的覆盖问题:
我们有一个2xN的长条形棋盘,然后用1x2的骨牌去覆盖整个棋盘。对于这个棋盘,一共有多少种不同的覆盖方法呢?
举个例子,对于长度为1到3的棋盘,我们有下面几种覆盖方式:
输入
第1行:1个整数N。表示棋盘长度。1≤N≤100,000,000
输出
第1行:1个整数,表示覆盖方案数 MOD 19999997
#include <iostream>
using namespace std;
struct matrix{
long long arr[2][2];
}base,res;
const int MOD = 19999997;
matrix matMulti(matrix a, matrix b)
{
matrix temp;
int i,j;
for(i=0; i<2; i++)
for(j=0; j<2; j++){
temp.arr[i][j] = 0;
for(int k=0; k<2; k++){
temp.arr[i][j] = temp.arr[i][j]%MOD+a.arr[i][k]*b.arr[k][j]%MOD;
}
}
return temp;
}
long long fastFibonacii(long n)
{
base.arr[0][0]=base.arr[0][1]=base.arr[1][0]=1;
base.arr[1][1]=0;
res.arr[0][1]=res.arr[1][0]=1;
res.arr[1][1]=0;
res.arr[0][0]=1;
while(n){
if(n&1){
res = matMulti(res, base);
}
base = matMulti(base,base);
n >>= 1;
}
return res.arr[0][1];
}
int main()
{
long n;
while(cin>>n){
cout<<fastFibonacii(n)%MOD<<endl;
}
system("pause");
return 0;
}
用定义一个结构体,重载运算符:
#include <iostream>
using namespace std;
const int MOD = 19999997;
struct matrix{ //重载结构体
public:
long long a;
long long b;
long long c;
long long d;
matrix &operator * (matrix &data){ //重载*
long long tempa = a;
long long tempb = b;
long long tempc = c;
long long tempd = d;
a = tempa*data.a%MOD+tempb*data.c%MOD;
b = tempa*data.b%MOD+tempb*data.d%MOD;
c = tempc*data.a%MOD+tempd*data.c%MOD;
d = tempc*data.b%MOD+tempd*data.d%MOD;
return *this;
}
matrix &operator = (matrix &data){ //重载&
a = data.a;
b = data.b;
c = data.c;
d = data.d;
return *this;
}
};
long long fastFibonacci(long n)
{
matrix res = {1,1,1,0};
matrix base = {1,1,1,0};
matrix temp;
n++;
while(n){
if(n&1){
res = res*base;
}
temp = base;
base = base*temp;
n >>=1;
}
return res.d;
}
int main()
{
long n;
while(cin>>n){
cout<<fastFibonacci(n)%MOD<<endl;
}
system("pause");
return 0;
}