luogu1357 花园 状态压缩 矩阵快速幂
题目大意
小L有一座环形花园,沿花园的顺时针方向,他把各个花圃编号为1~N(2<=N<=10^15)。他的环形花园每天都会换一个新花样,但他的花园都不外乎一个规则,任意相邻M(2<=M<=5,M<=N)个花圃中有不超过K(1<=K<M)个C形的花圃,其余花圃均为P形的花圃。请帮小L求出符合规则的花园种数Mod 1000000007。
题解
状态的设计
我们先不考虑环。我对状态的设计是f(i, j, k),i是以第i位起始,j是区间[i, i+m]中最后一个C的位置-i的值,k是[i, i+m]中C的数量,f是排列的种数。后来我认为j也不需要,f(i, k)就行了。但是此方法一个k无法表示出具体的排布状态,这是错误的。
我们看到M<=5,很容易想到用状态压缩来表示具体的状态。所以我们设计出f(i, S),i是位置,S是[i, i+M]中C的排布状态,f是排列的个数。递推式f(i + 1, S >> 1) += f(i, S), f(i + 1, (S >> 1) | (1 << M - 1) += f(i, S),其中涉及到的所有集合内元素个数都不超过K。
环的处理
我当时想到将长度为n的序列尾部再加一个长度为m的序列,从左往右递推,最后输出的结果便是sum{f(n, S)},S满足元素个数<=K,但考虑到这样会导致结尾m个花的排列状态和开头m个花的排列状态不一致而导致错误。于是我就卡住了。
正确的解决办法是枚举开头[1, m]的花的状态S,每次将其固定住,这样DP推导出的DP(n, S)都是由[m + 1, n + m]处花合法的排列得出的了。
矩阵快速幂优化
我们看到对于每一个状态S0,无论i是多少,可以使f(i, S0)去+=的出处f(i+1, S0')都是固定的。所以我们建立一个矩阵A,A(S1, S2)=[对任意i, f(i + 1, S2)需要+=f(i, S1)]。[]内判断为真即1,否则为0。这样,对于每一个开头[1, m]的花的状态S0,建立一个向量B,其中只有S0那一位的项为1(排列方式由S0知道肯定为1),最终的结果便是B*A^N。最后求和即可。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cassert>
using namespace std; #define ll long long
const int MAX_M = 7;
const ll P = 1000000007;
ll N, M, K; struct Matrix
{
private:
int TotRow, TotCol; public:
ll A[1 << MAX_M][1 << MAX_M]; void Clear()
{
memset(A, 0, sizeof(A));
} Matrix(int totRow, int totCol) :TotRow(totRow), TotCol(totCol) { Clear(); } Matrix operator * (const Matrix& a) const
{
assert(TotCol == a.TotRow);
Matrix ans(TotRow, a.TotCol);
for (int row = 0; row < TotRow; row++)
for (int col = 0; col < a.TotCol; col++)
for (int k = 0; k < TotCol; k++)
ans.A[row][col] = (ans.A[row][col] + (A[row][k] * a.A[k][col] % P)) % P;
return ans;
} Matrix Power(ll n)
{
Matrix ans(TotRow, TotCol);
for (int i = 0; i < TotRow; i++)
ans.A[i][i] = 1;
Matrix a = *this;
while (n)
{
if (n & 1)
ans = ans * a;
a = a * a;
n >>= 1;
}
return ans;
}
}; int main()
{
scanf("%lld%lld%lld", &N, &M, &K); static bool Exist[1 << MAX_M];
for (int S = 0; S < (1 << M); S++)
{
int cnt = 0;
for (int i = 0; i < M; i++)
cnt += (S & (1 << i)) > 0;
Exist[S] = cnt <= K;
} static Matrix g(1 << M, 1 << M);
for (int S = 0; S < (1 << M); S++)
{
if (Exist[S])
{
g.A[S][S >> 1] = 1;
if (Exist[(S >> 1) | (1 << M - 1)])
g.A[S][(S >> 1) | (1 << M - 1)] = 1;
}
} static Matrix powed = g.Power(N), start(1, 1 << M);
ll ans = 0;
for (int S = 0; S < (1 << M); S++)
{
if (Exist[S])
{
start.Clear();
start.A[0][S] = 1;
ans = (ans + (start * powed).A[0][S]) % P;
}
}
printf("%lld\n", ans);
}
luogu1357 花园 状态压缩 矩阵快速幂的更多相关文章
- 洛谷P1357 花园(状态压缩 + 矩阵快速幂加速递推)
题目链接:传送门 题目: 题目描述 小L有一座环形花园,沿花园的顺时针方向,他把各个花圃编号为1~N(<=N<=^).他的环形花园每天都会换一个新花样,但他的花园都不外乎一个规则,任意相邻 ...
- P1357 花园 状压 矩阵快速幂
题意 小L有一座环形花园,沿花园的顺时针方向,他把各个花圃编号为1~N(2<=N<=10^15).他的环形花园每天都会换一个新花样,但他的花园都不外乎一个规则,任意相邻M(2<=M& ...
- hihocoder第42周 3*N骨牌覆盖(状态dp+矩阵快速幂)
http://hihocoder.com/contest/hiho42/problem/1 给定一个n,问我们3*n的矩阵有多少种覆盖的方法 第41周做的骨牌覆盖是2*n的,状态转移方程是dp[i] ...
- hihocoder第42周 k*N骨牌覆盖(状态dp+矩阵快速幂)
上周的3*N的骨牌,因为状态只有8中,所以我们可以手算出状态转移的矩阵 但是这周是k*N,状态矩阵不好手算,都是我们改成用程序自动生成一个状态转移的矩阵就行了,然后用这个矩阵进行快速幂即可 枚举枚举上 ...
- 【BZOJ2004】公交线路(动态规划,状态压缩,矩阵快速幂)
[BZOJ2004]公交线路(动态规划,状态压缩,矩阵快速幂) 题面 BZOJ 题解 看到\(k,p\)这么小 不难想到状态压缩 看到\(n\)这么大,不难想到矩阵快速幂 那么,我们来考虑朴素的\(d ...
- [luogu1357] 花园 [dp+矩阵快速幂]
题面: 传送门 思路: 把P形花圃记录为0,C形记录为1,那么一段花圃就可以状态压缩成一个整数 那么,我们可以有这样的状压dp: dp[i][S]表示前i个花圃,最后m个的状态为S的情况 如果这是一条 ...
- P1357 花园 (矩阵快速幂+ DP)
题意:一个只含字母C和P的环形串 求长度为n且每m个连续字符不含有超过k个C的方案数 m <= 5 n <= 1e15 题解:用一个m位二进制表示状态 转移很好想 但是这个题是用矩阵快速 ...
- bzoj2004 矩阵快速幂优化状压dp
https://www.lydsy.com/JudgeOnline/problem.php?id=2004 以前只会状压dp和矩阵快速幂dp,没想到一道题还能组合起来一起用,算法竞赛真是奥妙重重 小Z ...
- ZZNU 2182 矩阵dp (矩阵快速幂+递推式 || 杜教BM)
题目链接:http://47.93.249.116/problem.php?id=2182 题目描述 河神喜欢吃零食,有三种最喜欢的零食,鱼干,猪肉脯,巧克力.他每小时会选择一种吃一包. 不幸的是,医 ...
随机推荐
- [ POI 2017 ] Podzielno
\(\\\) \(Description\) \(B\)进制数,每个数字\(i(i\in [0,B-1])\)有\(A_i\)个.用这些数字组成一个最大的\(B\)进制数\(X\)(不能有前导零,不需 ...
- 编写第一个HTML5文件
1.3.1 HTML文件的编写方法 编写HTML文件主要有如下3种方法: 手工直接编写 由于HTML语言编写的文件是标准的ASCII文本文件,所以我们可以使用任何的文本编辑器来打开并编写HTML文件 ...
- 背包系列 hdu 3535 分组背包
题意: 有n组工作,现在有T分钟时间去做一些工作.每组工作里有m个工作,并且类型为s,s类型可以为0,1,2,分别表示至少选择该组工作的一项,至多选择该工作的一项,不限制选择.每个工作有ci,gi两个 ...
- JS——样式类的添加
1.注意current前有个空格 this.className = this.className + " current"; 2.直接将class所有的值替换成current th ...
- JS——null
变量被赋值为null,目的往往是为了销毁这个对象: var n1 = 1; n1 = null;
- js 零碎
function具有一个属性是length,表示希望接收到的命名参数的个数.可以通过arguments获取参数.arguments.callee表示函数本身,递归时有用,也可以通过arguments. ...
- 图论 Make Unique:有向图和无向图的一些算法
计算机科学入门资料之一的<算法与数据结构-C语言版>,覆盖了基础算法的几乎所有分支,其中的一个典型分支为图理论. 一个简介:图论基础-图数据结构基础 一个简洁的博客:图论基础,简列一本书 ...
- pptp服务故障
pptp服务故障记录 原文地址:http://www.cnblogs.com/caoguo/p/4994512.html 1.pptp部署是遇到开了防火墙端口不能拨号,拨号是提示错误如下: 但是关闭防 ...
- (转)Arcgis for javascript实现百度地图ABCD marker的效果
概述: 在我的博客中,有一篇相关的文章,这段时间,有很多人问我求源码,只是时间过去已长,源代码已找不到,乘着这个9.3放假,又重新实现了下,并相关代码做了优化,在此贴出来,方便大家使用. 相关文章地址 ...
- 洛谷——P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm
P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm 题意翻译 题目描述 每年,在威斯康星州,奶牛们都会穿上衣服,收集农夫约翰在N(1<=N< ...