题目1 : 骨牌覆盖问题·一
时间限制:
10000ms
单点时限:
1000ms
内存限制:
256MB
-
62247088
样例输出
-
17748018
描述
骨牌,一种古老的玩具。今天我们要研究的是骨牌的覆盖问题:
我们有一个2xN的长条形棋盘,然后用1x2的骨牌去覆盖整个棋盘。对于这个棋盘,一共有多少种不同的覆盖方法呢?
举个例子,对于长度为1到3的棋盘,我们有下面几种覆盖方式:
输入
第1行:1个整数N。表示棋盘长度。1≤N≤100,000,000
输出
第1行:1个整数,表示覆盖方案数 MOD 19999997
分析:
1、其实没有什么要分析的,因为官方给的提示已经够详细了(强烈推荐)。
2、总结一下:像斐波那契数列那种递归思路题,有许多解法。但是,时间复杂度上有质的飞越。下面我们就来分析分析:
(1)、首先,一般思路递归方法-----递归函数。
#include <iostream>
using namespace std;
int f(int n)
{
if(n<3)
return 1;
return f(n-1)+f(n-2);
}
int main()
{
int n;
cin>>n;
cout<<f(n)<<endl;
return 0;
}
#include <iostream>
using namespace std;
int main()
{
int n;
cin>>n;
long long a[100005]={1,1};
for(int i=2;i<n;i++)
a[i]=a[i-1]+a[i-2];
cout<<a[n-1]<<endl;
return 0;
}
#include <iostream>
using namespace std;
const int mod=1000000;
long long used[1000005];
long long f(int n)
{
if(used[n])
return used[n]%mod;
if(n<3)
return 1;
return used[n]=f(n-1)%mod+f(n-2)%mod;
}
int main()
{
int n;
cin>>n;
long long ans=f(n);
cout<<ans<<endl;
return 0;
}
贴上我一开始做这道题的代码。
#include <iostream>
using namespace std;
typedef long long LL;
LL n,dp[1000005];
const LL MOD=19999997;
LL cal(LL x)
{
if(x<1000000&&dp[x])
return dp[x]%MOD;
if(x==1)
return 1;
if(x==2)
return 2;
if(x<1000000)
return dp[x]=cal(x-1)%MOD+cal(x-2)%MOD;
else
return cal(x-1)%MOD+cal(x-2)%MOD;
}
int main()
{
cin>>n;
LL sum=cal(n)%MOD;
cout<<sum;
return 0;
}
(4)最后,就是本道题 所提示的思路算法,矩阵乘法+快速幂。本题AC码:
LANGUAGE:C++
CODE:
#include <iostream>
using namespace std;
typedef long long LL;
LL n,M[4]={0,1,1,1},tmp[4]={1,0,0,1},t[4];
const int MOD=19999997;
void cal(LL a[],LL b[])
{
t[0]=a[0]*b[0]+a[1]*b[2];
t[1]=a[0]*b[1]+a[1]*b[3];
t[2]=a[2]*b[0]+a[3]*b[2];
t[3]=a[2]*b[1]+a[3]*b[3];
return ;
}
int pow_quick(LL nn)
{
while(nn){
if(nn&1){
cal(tmp,M);
for(int i=0;i<4;i++)
tmp[i]=t[i]%MOD;
}
cal(M,M);
for(int i=0;i<4;i++)
M[i]=t[i]%MOD;
nn>>=1;
}
return 0;
}
int main()
{
cin>>n;
pow_quick(n);
// for(int i=0;i<4;i++)
// cout<<tmp[i]<<endl;
cout<<tmp[3]%MOD;
return 0;
}