题目链接:http://hihocoder.com/problemset/problem/1143?sid=1485086
描述
骨牌,一种古老的玩具。今天我们要研究的是骨牌的覆盖问题:
我们有一个2xN的长条形棋盘,然后用1x2的骨牌去覆盖整个棋盘。对于这个棋盘,一共有多少种不同的覆盖方法呢?
举个例子,对于长度为1到3的棋盘,我们有下面几种覆盖方式:
输入
第1行:1个整数N。表示棋盘长度。1≤N≤100,000,000
输出
第1行:1个整数,表示覆盖方案数 MOD 19999997
样例输入
62247088
样例输出
17748018
读完题目发现是熟悉的斐波那契,很高兴的dp,然后T了,所以要开始优化了
矩阵快速幂
那么问题来了,系数矩阵怎么取呢,首项是n=2的斐波那契还是一样的系数吗
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int mod = 19999997;
const int MAX = 1e8+5;
struct Matrix{
ll a[3][3];
Matrix() { memset(a,0,sizeof(a)); }
Matrix operator * (const Matrix &rhs){
Matrix res;
for(int i=1;i<=2;i++)
for(int j=1;j<=2;j++)
for(int k=1;k<=2;k++)
res.a[i][j] = (res.a[i][j]+a[i][k]*rhs.a[k][j])%mod;
return res;
}
}res,G;
void mpow(int n){
while(n>0){
if(n%2==1)
res = res*G;
G=G*G;
n>>=1;
}
}
int main(){
int n;
res.a[1][1] = res.a[2][2] = 1;
G.a[1][2]=G.a[2][1]=G.a[2][2]=1;
scanf("%d",&n);
mpow(n);
// for(int i=1;i<=2;i++){
// for(int j=1;j<=2;j++)
// printf("%d ",res.a[i][j]);
// printf("\n");
// }
printf("%lld\n",res.a[2][2]);
return 0;
}