POJ3420 Quad Tiling DP + 矩阵高速幂
题目大意是用1*2的骨牌堆积成4*N的矩形。一共同拥有多少种方法,N不超过10^9。
这题和以前在庞果网上做过的一道木块砌墙差点儿一样。
由于骨牌我们能够横着放。竖着放。我们如果以4为列,N为行这样去看,而且在骨牌覆盖的位置上置1,所以一共最多有16种状态。我们在第M行放骨牌的时候,第M+1行的状态也是有可能被改变的,设S(i,j)表示某一行状态为i时,将其铺满后下一行状态为j的方案书。考虑下如果我们让矩阵S和S相乘会有什么意义。考虑一下会发现S*S的意义当某行状态为i。接着其后面第2行的状态为j的可行方案数,一般地,S^n则代表接下来第n行状态为j的方案数,这里N非常大,我们能够用高速幂对矩阵的幂进行加速。
对于S矩阵的最初状态我们能够穷尽搜索来求。
#include <stdlib.h>
#include <stdio.h>
#include <vector>
#include <math.h>
#include <string.h>
#include <string>
#include <iostream>
#include <queue>
#include <list>
#include <algorithm>
#include <stack>
#include <map> #include<iostream>
#include<cstdio>
using namespace std;
int State[16][16];
int Start[16][16];
int IMod; void InitState(int ori, int s, int p)
{
bool isfull = true;
for (int i = 0; i < 4; i++)
{
if (((s >> i) & 1) == 0)
{
//竖着放
InitState(ori, s | (1 << i), p | (1 << i));
//横着放
if (i < 3 && ((s >> (i + 1)) & 1) == 0)
{
int tp = s | (1 << i);
tp |= (1 << (i + 1));
InitState(ori ,tp, p);
}
isfull = false;
break;
}
}
if (isfull)
{
State[ori][p] += 1;
}
} void Product(int a[][16], int b[][16], int res[][16])
{
for (int i = 0; i < 16;i++)
{
for (int j = 0; j < 16; j++)
{
res[i][j] = 0;
for (int k = 0; k < 16; k++)
{
res[i][j] += (a[i][k] * b[k][j] % IMod);
res[i][j] %= IMod;
}
}
}
} void QProduct(int p[][16], int res[16][16], int n)
{
memset(res, 0, sizeof(int) * 16 * 16);
int tmp[2][16][16];
int tmpres[16][16];
memcpy(tmp[0], p, sizeof(int) * 16 * 16);
int i = 0;
for (int k = 0; k < 16; k++)
{
res[k][k] = 1;
}
while (n)
{ if (n & 1)
{
memcpy(tmpres, res, sizeof(int) * 16 * 16);
Product(tmpres, tmp[i & 1], res);
}
Product(tmp[i & 1], tmp[i & 1], tmp[(i + 1) & 1]);
i++;
n = n >> 1;
}
} int main()
{
#ifdef _DEBUG
freopen("d:\\in.txt", "r", stdin);
#endif
int n, m;
memset(State, 0, sizeof(State));
for (int i = 0; i < 16; i++)
{
InitState(i, i, 0);
} int finstates[16][16];
int res[16][16];
memset(Start, 0, sizeof(Start));
Start[0][0] = 1;
while (scanf("%d %d", &n, &m) != EOF)
{
if (n == 0 || m == 0)
{
break;
}
IMod = m;
QProduct(State, finstates, n);
Product(Start, finstates, res);
int ans = 0;
for (int i = 0; i < 16; i++)
{
ans += res[i][0];
ans %= IMod;
}
printf("%d\n", ans);
}
return 0;
}
POJ3420 Quad Tiling DP + 矩阵高速幂的更多相关文章
- HDU 5411 CRB and puzzle (Dp + 矩阵高速幂)
CRB and Puzzle Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) T ...
- poj 3744 Scout YYF I (可能性DP+矩阵高速功率)
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 5062 Accepted: 1370 Description YYF i ...
- Codeforces Round #307 (Div. 2) D. GukiZ and Binary Operations (矩阵高速幂)
题目地址:http://codeforces.com/contest/551/problem/D 分析下公式能够知道,相当于每一位上放0或者1使得最后成为0或者1.假设最后是0的话,那么全部相邻位一定 ...
- hdu 5411 CRB and Puzzle 矩阵高速幂
链接 题解链接:http://www.cygmasot.com/index.php/2015/08/20/hdu_5411/ 给定n个点 常数m 以下n行第i行第一个数字表示i点的出边数.后面给出这些 ...
- bnuoj 34985 Elegant String DP+矩阵快速幂
题目链接:http://acm.bnu.edu.cn/bnuoj/problem_show.php?pid=34985 We define a kind of strings as elegant s ...
- UVA 11551 - Experienced Endeavour(矩阵高速幂)
UVA 11551 - Experienced Endeavour 题目链接 题意:给定一列数,每一个数相应一个变换.变换为原先数列一些位置相加起来的和,问r次变换后的序列是多少 思路:矩阵高速幂,要 ...
- UVA10518 - How Many Calls?(矩阵高速幂)
UVA10518 - How Many Calls?(矩阵高速幂) 题目链接 题目大意:给你fibonacci数列怎么求的.然后问你求f(n) = f(n - 1) + f(n - 2)须要多少次调用 ...
- HDU2842-Chinese Rings(递推+矩阵高速幂)
pid=2842">题目链接 题意:求出最少步骤解出九连环. 取出第k个的条件是,k-2个已被取出,k-1个仍在支架上. 思路:想必九连环都玩过吧,事实上最少步骤就是从最后一个环開始. ...
- HDU2276 - Kiki & Little Kiki 2(矩阵高速幂)
pid=2276">题目链接 题意:有n盏灯.编号从1到n.他们绕成一圈,也就是说.1号灯的左边是n号灯.假设在第t秒的时候,某盏灯左边的灯是亮着的,那么就在第t+1秒的时候改变这盏灯 ...
随机推荐
- 有关Kali处理源的方法
sudo apt-get update 更新源sudo apt-get install package 安装包sudo apt-get remove package 删除包sudo apt-cach ...
- django第10天(聚合查询,常用字段)
django第10天 聚合查询 聚合函数的使用场景 单独使用:不分组,只查聚合结果 分组使用:按字段分组,可查分组字段与聚合结果 导入聚合函数 from django.db.models import ...
- Day07 数据类型(列表,元组,字典,集合)常用操作和内置方法
数据类型 列表list: 用途:记录多个值(同种属性) 定义方式:[]用逗号分隔开多个任意类型的值 list()造出来的是列表,参数是可迭代对像,也就是可以使用for循环的对像 传入字典,出来的列表元 ...
- Day05基本运算符,if判断和while循环
day05 1.常量 变量名全大写 2.基本运算符 ①算术运算 10/3除法 10//3取整 10*3乘法 10**3幂 ②赋值运算 增量赋值 age += 1#age = age + 1 age * ...
- luogu3629 [APIO2010]巡逻
创造一个环出来,可以让环上的边都只访问一次. 对于 \(k=1\),答案就是树的直径两边连起来. 倘若 \(k=2\),那就先按照 \(k=1\) 的求一遍,然后我们发现,如果第二条加的边构成的环和第 ...
- POJ-2187 Beauty Contest,旋转卡壳求解平面最远点对!
凸包(旋转卡壳) 大概理解了凸包A了两道模板题之后在去吃饭的路上想了想什么叫旋转卡壳呢?回来无聊就搜了一下,结果发现其范围真广. 凸包: 凸包就是给定平面图上的一些点集(二维图包),然后求点集组成的 ...
- 九度oj 题目1090:路径打印
题目描述: 给你一串路径,譬如:a\b\c a\d\e b\cst d\你把这些路径中蕴含的目录结构给画出来,子目录直接列在父目录下面,并比父目录向右缩一格,就像这样:a b c d ...
- BZOJ 1821 [JSOI2010]Group 部落划分:MST
Description 聪聪研究发现,荒岛野人总是过着群居的生活,但是,并不是整个荒岛上的所有野人都属于同一个部落,野人们总是拉帮结派形成属于自己的部落,不同的部落之间则经常发生争斗.只是,这一切都成 ...
- Linux(10):期中架构(2)--- NFS存储服务 & 实时同步
1. 共享存储服务概念: # NFS是Network File System的缩写,中文意思是网络文件系统, # 它的主要功能是通过网络(一般是局域网)让不同的主机系统之间可以共享文件或目录. 2. ...
- android soap webservers 无法执行 报错 ht.call(SOAP_ACTION, envelope);解决方法
1.可能没有加入网络访问权限,在Manifest里面加入,<uses-permission android:name="android.permission.INTERNET" ...