当前位置: 代码迷 >> 综合 >> zcmu 1618: 骨牌覆盖1
  详细解决方案

zcmu 1618: 骨牌覆盖1

热度:45   发布时间:2023-12-26 10:29:24.0

 

1618: 骨牌覆盖1

Time Limit: 1 Sec  Memory Limit: 128 MB

Submit: 378  Solved: 180

[Submit][Status][Web Board]

Description

?我们有一个2xN的长条形棋盘,然后用1x2的骨牌去覆盖整个棋盘。对于这个棋盘,一共有多少种不同的覆盖方法呢?

Input

输入n,n<=100000

Output

覆盖方案总数对19999997取余

Sample Input

1

2

Sample Output

1

2

 

分析:

  1. 找到规律后其实就是求斐波那契数列咯,然后只是这里n会很大,如果递归或者枚举的话会很麻烦,所以用到了矩阵;

  2. 对于 Fibonacci 数列,我们希望找到一个2x2的矩阵M,使得(a, b) x M = (b, a+b),其中(a, b)和(b, a+b)都是1x2的矩阵。显然,只要 M = [0, 1; 1, 1];

  3. 接下来,找规律!

        即可得到第n项的公式;

当我看到绿色的Accept的时候!!可以说是爆炸开心了!!!

代码

#include<bits/stdc++.h>
using namespace std;
const int NUM = 19999997;	void cal(long long a[2][2],long long b[2][2])//a用来储存前面的矩阵,b用来存储中间的矩阵 
{long long c[2][2];//c是等号后面的矩阵 c[0][0]=(a[0][0]*b[0][0]+a[0][1]*b[1][0])%NUM;c[0][1]=(a[0][0]*b[0][1]+a[0][1]*b[1][1])%NUM;c[1][0]=(a[1][0]*b[0][0]+a[1][1]*b[1][0])%NUM;c[1][1]=(a[1][0]*b[0][1]+a[1][1]*b[1][1])%NUM;a[0][0]=c[0][0];//将c再赋值给a a[0][1]=c[0][1];a[1][0]=c[1][0];a[1][1]=c[1][1];}
int main()
{long int n,cnt=0;//cin>>n;while(scanf("%lld",&n)!=EOF){long long a[2][2]={1,0,0,1};long long m[2][2]={0,1,1,1};//cout<<m[2][2]<<endl;if(n==2){cout<<"2\n";}else {while(n--){cal(a,m);}cout<<a[1][1]<<endl;}}return 0;}