ZCMU-1618-骨牌覆盖(矩阵乘法+快速幂)

1618: 骨牌覆盖1

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 264   Solved: 124
[ Submit][ Status][ Web Board]

Description

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

Input

输入n,n<=100000

Output

覆盖方案总数对19999997取余

Sample Input

1
2

Sample Output

1
2

【解析】
这道题的话其实我们只要列举出前面几个数我们数一数方案我们就能知道是什么样的规律了,感觉很多题都是斐波那契数列,就算蒙,说不定也能蒙对了,还有这道题数据不大,所以我们更加好做,不过我在这里要说一下万一数据很大,我们怎么求斐波那契数列?在这里我要说一下矩阵乘法了。什么是矩阵乘法?把这些概念搞懂就差不多了。 1.当矩阵A的列数等于矩阵B的行数时,A与B可以相乘。2.矩阵C的行数等于矩阵A的行数,C的列数等于B的列数。3.乘积C的第m行第n列的元素等于矩阵A的第m行的元素与矩阵B的第n列对应元素乘积之和。比如
我们可以用矩阵乘法来求n项,我们希望找到一个2x2的矩阵M,使得(a, b) x M = (b, a+b),其中(a, b)和(b, a+b)都是1x2的矩阵。a代表前一项,b代表的是后一项。我们这里M只要取[0,1;1,1];至于为什么我们可以自己去验证下。我们可以看一下图片上的例子。
这就是我们要做的事情矩阵直接不断的成不断的乘,最终我们的式子是这样子的
这个时候n其实是巨大的,我们这个时候想要快速的求出我们就需要用到快速幂的算法了。关于快速幂的问题可以看看这里http://blog.csdn.net/zcmuczx/article/details/53962502
我们很容易的知道a的n次方我们要求,就把n转换成二进制来求,因为你看5如果给他编码我们就取后几位101遇到1就表示它要开始乘了,就好比a的5次方其实就是a的4次方乘a所以我们遇到末尾的1相当于遇到5的1次乘起来,遇到倒数第三位的1就是5的四次了大家可以自己试一下。大概就是这么的思路接下来具体的看代码。
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
#define LL long long
#define MOD 19999997
LL N;
int i,j;
struct Matrlc
{
    LL mapp[2][2];//定义结构体,元素是一个矩阵
} ans,base;
Matrlc mult(Matrlc a,Matrlc b)
{
    Matrlc c;
    for(int i=0; i<2; i++)
    {
        for(int j=0; j<2; j++)
        {
            c.mapp[i][j]=0;
            for(int k=0; k<2; k++)//矩阵乘法
            {
                c.mapp[i][j]+=(a.mapp[i][k]*b.mapp[k][j])%MOD;//这里是比如行的元素乘列的元素
            }
            c.mapp[i][j]%=MOD;
        }
    }
    return c;
}
LL pow(LL n)
{
    base.mapp[0][0] =0;
    base.mapp[0][1]=base.mapp[1][0]=base.mapp[1][1]=1;//初始化矩阵成0,1,1,1;
    ans.mapp[0][0] =1; ans.mapp[0][1] =0;// 把第一个矩阵我把他设为1,0,0,0,这样的话其实只有第一行的元素是有用的经过一次乘法
    ans.mapp[1][0]= ans.mapp[1][1] = 0;//变成了1,1,0,0这样就表示f[1]为1其实这样才是初始状态,所以我们下面才要pow(N+1)
    while(n)
    {
        if(n&1)
            ans=mult(ans,base);
        base=mult(base,base);//矩阵乘法
        n>>=1;
    }
    return ans.mapp[0][1]%MOD;
}
int main()
{
   while(~scanf("%lld",&N))
   {
   printf("%lld\n",pow(N+1)%MOD);
   }
   return 0;
}


### 回答1: zcmu 1093 简单计算器是一道编程题目,要求实现一个简单的计算器,能够进行加、减、乘、除四种基本运算。该题目主要考察编程基础能力和算法思维能力,需要熟练掌握基本的运算符和控制语句,能够设计合理的算法实现计算器功能。 ### 回答2: zcmu 1093 简单计算器是一种基于计算机技术的工具,用于进行基本算术运算,如加减乘除等。它能够简化我们在日常生活中的计算工作,提高计算效率,减少出错率。 使用zcmu 1093 简单计算器非常简单,只需输入需要计算的数字和符号,就能够得到计算结果。它可以进行多个数字之间的复杂运算,同时还支持小数、百分数、平方根等复杂运算。另外,zcmu 1093 简单计算器还可以存储中间计算结果,方便我们进行多步计算或调整计算过程。 除了日常的计算工作,zcmu 1093 简单计算器还可用于科学计算、工程设计等领域。许多专业软件都是基于简单计算器原理设计的,它们具有更高的计算精度和更复杂的运算能力,能够支持更高级别的科学计算和技术分析。 总之,zcmu 1093 简单计算器在日常生活中有着广泛的应用,它使我们的计算工作变得更加高效、准确。并且,随着科技的不断发展,这种计算工具也在不断地更新和改进,为我们的计算工作提供更加便捷、多样化的选择。 ### 回答3: ZCMU 1093 简单计算器是一道基础的算法题目,需要实现一个简单的计算器程序,支持加、减、乘、除四种基本运算,可以对两个整数进行运算并输出结果。 要实现这道题目,首先需要根据输入的运算符来判断应该进行的运算类型,并根据运算符的不同,执行不同的计算操作。同时,应注意除数不能为零的情况,避免程序出现异常。 在编写程序的过程中,可以使用 switch case 语句来判断不同的运算类型,并执行相应的计算操作。同时,为了能有效地判断输入的运算符,可以使用输入字符串的方式进行处理,提取出运算符进行比较。 此外,在程序中还需要进行合法性判断,确保输入的数字均为整数且在合理的范围内,以避免程序运行出现异常情况。同时,还需要考虑输入格式的问题,应确保输入的数字和运算符符合题目要求。 综上所述,ZCMU 1093 简单计算器是一道基础的算法题目,需要实现一个简单的计算器程序,支持加、减、乘、除四种基本运算,注意程序的合法性判断和输入格式的处理,能够熟练地运用 switch case 等语句完成程序的编写。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值