2015微软编程之美资格赛骨牌覆盖(矩阵快速幂)

由于棋盘只有两行,所以如果第i列的骨牌竖着放,那么就转移为第1列到第i-1列骨牌有多少种摆法

如果第一行第i列骨牌横着放,那么第二行第i列也要横着放,那么就转移为了第1列到第i-2列骨牌有多少种方法

dp[i] = dp[i-1] + dp[i-2],但是列数太多了。 这种递推的算式可以用矩阵快速幂来优化

所以时间复杂度瞬间变为O(logn)

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 #include <algorithm>
 5 #include <iostream>
 6 #include <queue>
 7 #include <stack>
 8 #include <vector>
 9 #include <map>
10 #include <set>
11 #include <string>
12 #include <math.h>
13 using namespace std;
14 typedef long long LL;
15 const int INF = 1<<30;
16 LL ans;
17 const int MOD = 19999997;
18 //矩阵快速幂   a[i] = a[i-1] + a[i-2]
19
20 struct Matrix
21 {
22     LL m[2][2];
23 };
24 Matrix operator*(const Matrix &lhs, const Matrix &rhs)
25 {
26     Matrix ret;
27     for(int i=0; i<2; ++i)
28         for(int j=0; j<2; ++j)
29             ret.m[i][j] = 0;
30     for(int i=0; i<2; ++i)
31         for(int j=0; j<2; ++j)
32             for(int k=0; k<2; ++k)
33                 if(lhs.m[i][k]!=0 && rhs.m[k][j]!=0)
34                     ret.m[i][j] = (ret.m[i][j] + lhs.m[i][k] * rhs.m[k][j])%MOD;
35
36     return ret;
37 }
38 Matrix operator^(Matrix a, int k)
39 {
40     Matrix ret;
41     for(int i=0; i<2; ++i)
42         for(int j=0; j<2; ++j)
43             ret.m[i][j] = 1;
44     ret.m[1][1] = 0;
45     while(k)
46     {
47         if(k&1)
48             ret = ret * a;
49         k>>=1;
50         a = a * a;
51     }
52     return ret;
53 }
54
55 int main()
56 {
57     int n;
58     while(scanf("%d",&n)!=EOF)
59     {
60         Matrix tmp;
61         for(int i=0; i<2; ++i)
62             for(int j=0; j<2; ++j)
63                 tmp.m[i][j] = 1;
64         tmp.m[1][1] = 0;
65         Matrix final = tmp ^ (n-3);
66         LL ans = (2 * final.m[0][0] + 1 * final.m[1][0])%MOD;
67         printf("%lld\n",ans);
68     }
69     return 0;
70 }

时间: 2024-11-06 07:39:54

2015微软编程之美资格赛骨牌覆盖(矩阵快速幂)的相关文章

编程之美 --1 : 骨牌覆盖问题&#183;一

题目1 : 骨牌覆盖问题·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 骨牌,一种古老的玩具.今天我们要研究的是骨牌的覆盖问题:我们有一个2xN的长条形棋盘,然后用1x2的骨牌去覆盖整个棋盘.对于这个棋盘,一共有多少种不同的覆盖方法呢?举个例子,对于长度为1到3的棋盘,我们有下面几种覆盖方式: 提示:骨牌覆盖 提示:如何快速计算结果 输入 第1行:1个整数N.表示棋盘长度.1≤N≤100,000,000 输出 第1行:1个整数,表示覆盖方案数 MOD 1999

编程之美资格赛 大神与三位小伙伴

题目2 : 大神与三位小伙伴 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 L国是一个有着优美景色且物产丰富的国家,很多人都喜欢来这里旅游并且喜欢带走一些纪念品,大神同学也不例外.距离开L国的时间越来越近了,大神同学正在烦恼给她可爱的小伙伴们带什么纪念品好,现在摆在大神同学面前的有三类纪念品A, B, C可以选择,每类纪念品各有N种.其中种类为A_i, B_i, C_i的纪念品价值均为i, 且分别有N+1-i个剩余.现在大神同学希望在三类纪念品中各挑选一件然后赠送给

hihoCoder 1143 : 骨牌覆盖问题&#183;一(递推,矩阵快速幂)

[题目链接]:click here~~ 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 骨牌,一种古老的玩具.今天我们要研究的是骨牌的覆盖问题: 我们有一个2xN的长条形棋盘,然后用1x2的骨牌去覆盖整个棋盘.对于这个棋盘,一共有多少种不同的覆盖方法呢? 举个例子,对于长度为1到3的棋盘,我们有下面几种覆盖方式: 提示:骨牌覆盖 提示:如何快速计算结果 输入 第1行:1个整数N.表示棋盘长度.1≤N≤100,000,000 输出 第1行:1个整数,表示覆盖方案数 M

hihoCoder #1151 : 骨牌覆盖问题&#183;二 (矩阵快速幂,DP)

题意:给一个3*n的矩阵,要求用1*2的骨牌来填满,有多少种方案? 思路: 官网题解用的仍然是矩阵快速幂的方式.复杂度O(logn*83). 这样做需要构造一个23*23的矩阵,这个矩阵自乘n-1次,再来乘以初始矩阵init{0,0,0,0,0,0,0,1}后,变成矩阵ans{x,x,x,x,x,x,x,y},y就是答案了,而x不必管. 主要在这个矩阵的构造,假设棋盘是放竖直的(即n*3),那么考虑在第i行进行填放,需要考虑到第i-1行的所有可能的状态(注意i-2行必须是已经填满了,否则第i行无

题目1 : 骨牌覆盖问题&#183;二 (矩阵快速幂+分析状态的表示+题目的提示分析很好很经典)

题目1 : 骨牌覆盖问题·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上一周我们研究了2xN的骨牌问题,这一周我们不妨加大一下难度,研究一下3xN的骨牌问题? 所以我们的题目是:对于3xN的棋盘,使用1x2的骨牌去覆盖一共有多少种不同的覆盖方法呢? 首先我们可以肯定,奇数长度一定是没有办法覆盖的:对于偶数长度,比如2,4,我们有下面几种覆盖方式: [week42_1.PNG] 提示:3xN骨牌覆盖 输入 第1行:1个整数N.表示棋盘长度.1≤N≤100,00

hiho_41周_骨牌覆盖一_招规律+矩阵快速幂

题目 骨牌,一种古老的玩具.今天我们要研究的是骨牌的覆盖问题: 我们有一个2xN的长条形棋盘,然后用1x2的骨牌去覆盖整个棋盘.对于这个棋盘,一共有多少种不同的覆盖方法呢? 举个例子,对于长度为1到3的棋盘,我们有下面几种覆盖方式: 输入 第1行:1个整数N.表示棋盘长度.1≤N≤100,000,000 输出 第1行:1个整数,表示覆盖方案数 MOD 19999997 样例输入 62247088 样例输出 17748018         前面几组一写,,很容易就能发现规律,是一个线性递推,甚至

题目1 : 骨牌覆盖问题&#183;一 (线性递推+矩阵快速幂)

题目来源 hiho一下 第四十一周 正在进行: 2天05小时28分钟25秒 首页 题目列表 我的提交 排名 讨论 报名人数:1264 题目1 : 骨牌覆盖问题·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 骨牌,一种古老的玩具.今天我们要研究的是骨牌的覆盖问题: 我们有一个2xN的长条形棋盘,然后用1x2的骨牌去覆盖整个棋盘.对于这个棋盘,一共有多少种不同的覆盖方法呢? 举个例子,对于长度为1到3的棋盘,我们有下面几种覆盖方式: 提示:骨牌覆盖 提示:如何快速

[2015编程之美] 资格赛C

#1150 : 基站选址 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 需要在一个N × M的网格中建立一个通讯基站,通讯基站仅必须建立在格点上. 网格中有A个用户,每个用户的通讯代价是用户到基站欧几里得距离的平方. 网格中还有B个通讯公司,维护基站的代价是基站到最近的一个通讯公司的路程(路程定义为曼哈顿距离). 在网格中建立基站的总代价是用户通讯代价的总和加上维护基站的代价,最小总代价. 输入 第一行为一个整数T,表示数据组数. 每组数据第一行为四个整数:N, M

2015编程之美资格赛 回文子序列个数

时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给定字符串,求它的回文子序列个数.回文子序列反转字符顺序后仍然与原序列相同.例如字符串aba中,回文子序列为”a”, “a”, “aa”, “b”, “aba”,共5个.内容相同位置不同的子序列算不同的子序列. 输入 第一行一个整数T,表示数据组数.之后是T组数据,每组数据为一行字符串. 输出 对于每组数据输出一行,格式为”Case #X: Y”,X代表数据编号(从1开始),Y为答案.答案对100007取模. 数据范围