洛谷 P1357 花园 解题报告
P1357 花园
题目描述
小\(L\)有一座环形花园,沿花园的顺时针方向,他把各个花圃编号为\(1~N(2<=N<=10^{15})\)。他的环形花园每天都会换一个新花样,但他的花园都不外乎一个规则,任意相邻\(M(2<=M<=5,M<=N)\)个花圃中有不超过\(K(1<=K<M)\)个\(C\)形的花圃,其余花圃均为\(P\)形的花圃。
例如,\(N=10,M=5,K=3\)。则
\(CCPCPPPPCC\)是一种不符合规则的花圃;
\(CCPPPPCPCP\)是一种符合规则的花圃。
请帮小\(L\)求出符合规则的花园种数\(Mod\) 1000000007
由于请您编写一个程序解决此题。
输入输出格式
输入格式:
一行,三个数\(N,M,K\)。
输出格式:
花园种数\(Mod\) 1000000007
说明
40%的数据中,\(N<=20\);
60%的数据中,\(M=2\);
80%的数据中,\(N<=10^5\)。
100%的数据中,\(N<=10^{15}\)。
这道题的思维难度是真的大(也可能是我菜)
请顺着看(我就是因为直接看别人题解没彻底理解前面的就去往后翻导致理解了很久)
80分给了状压DP
不考虑环时
令\(dp[i][j]\)代表当进行到第\(i\)个位置时,前\(M\)位的状态为\(j\)
\(dp[i][j]=dp[i-1][k]\),\(k\)为合法的前一位状态。
关于状压的思路,有两个导向性。
(1) \(2<=M<=5\)
(2) 当进行转移时,要想知道合不合法得知道前\(M\)位上的所有数。
当然,如果想不到如何处理环,状压的80分也白瞎。
想想在状压中,我们的状态实质上是一个区间,我们进行递推的时候,实际上相当于把这个区间向右滑动。
如果我们这时候只对一个初始合法区间\(j_0\)进行移动,当移动了\(n\)次以后,它可能到达很多个状态。但是如果它和自己重合了,不就连成了一个环了吗?
这时候\(dp[n][j_0]\)就代表只移动合法区间\(j_0\)所构成的环的方案数。
我们把每个初始合法区间都做一次这样的状压\(DP\),统计答案。
复杂度:\(O(M!^3*N)\)
当然实际上我们通过预处理,可以得到类似\(dx[i][j]\)这样的数组,表示状态\(i\)是否可以到达状态\(j\)。使复杂度远远达不到上界。
我们发现,\(N\)的长度和\(dx[i][j]\)没有什么关系,而\(dx[i][j]\)又是一个矩阵。
那么当忽略\(i\)这一维度时,\(dp[j]\)通过\(dx[i][j]\)向后一位进行递推,不就是矩阵乘法吗?
左边是推到某一位了,和右边矩阵相乘得到下一位。
可以直接用矩阵快速幂求解可达性矩阵的\(N\)次方,然后与每一个初始合法状态相乘。
我们发现,可达性矩阵和第\(j\)个状态的初始矩阵进行相乘后,只能取\((j,j)\)位置的值,所以最终的答案即是可达性矩阵乘方后对角线值之和。
Code:
#include <cstdio>
#include <cstring>
#define ll long long
const int N=123;
const ll mod=1e9+7;
ll n;
int m,k,len;
struct matrix
{
ll dx[N][N];
matrix()
{
memset(dx,0,sizeof(dx));
}
matrix friend operator *(matrix n1,matrix n2)
{
matrix n3;
for(int i=0;i<=len;i++)
for(int j=0;j<=len;j++)
for(int k=0;k<=len;k++)
n3.dx[i][j]=(n3.dx[i][j]+n1.dx[i][k]*n2.dx[k][j])%mod;
return n3;
}
}d,f;
bool check(int x)
{
int cnt=k;
while(x)
{
cnt--;
x-=x&-x;
}
return cnt>=0;
}
void init()
{
scanf("%lld%d%d",&n,&m,&k);//m中不超过k个1
len=(1<<m)-1;
for(int i=0;i<=len;i++)
{
if(!check(i))
continue;
int to=(i<<1)&len;
if(!check(to))
continue;
d.dx[to][i]=1;
to=to|1;
if(!check(to))
continue;
d.dx[to][i]=1;
}
for(int i=0;i<=len;i++)
f.dx[i][i]=1;
}
void quick_pow()
{
while(n)
{
if(n&1)
f=f*d;
d=d*d;
n>>=1;
}
}
void work()
{
quick_pow();
ll ans=0;
for(int i=0;i<=len;i++)
ans=(ans+f.dx[i][i])%mod;
printf("%lld\n",ans);
}
int main()
{
init();
work();
return 0;
}
2018.7.2
洛谷 P1357 花园 解题报告的更多相关文章
- 题解:洛谷P1357 花园
题解:洛谷P1357 花园 Description 小 L 有一座环形花园,沿花园的顺时针方向,他把各个花圃编号为 \(1∼n\).花园 \(1\) 和 \(n\) 是相邻的. 他的环形花园每天都会换 ...
- 洛谷 P2058 海港 解题报告
P2058 海港 题目描述 小K是一个海港的海关工作人员,每天都有许多船只到达海港,船上通常有很多来自不同国家的乘客. 小K对这些到达海港的船只非常感兴趣,他按照时间记录下了到达海港的每一艘船只情况: ...
- 洛谷 P3956 棋盘 解题报告
P3956 棋盘 题目描述 有一个\(m×m\)的棋盘,棋盘上每一个格子可能是红色.黄色或没有任何颜色的.你现在要从棋盘的最左上角走到棋盘的最右下角. 任何一个时刻,你所站在的位置必须是有颜色的(不能 ...
- 洛谷 P1979 华容道 解题报告
P1979 华容道 题目描述 小\(B\)最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时 ...
- BZOJ 3545 / 洛谷 P4197 Peaks 解题报告
P4197 Peaks 题目描述 在\(\text{Bytemountains}\)有\(N\)座山峰,每座山峰有他的高度\(h_i\).有些山峰之间有双向道路相连,共\(M\)条路径,每条路径有一个 ...
- 虔诚的墓主人(BZOJ1227)(洛谷P2154)解题报告
题目描述 小W是一片新造公墓的管理人.公墓可以看成一块N×M的矩形,矩形的每个格点,要么种着一棵常青树,要么是一块还没有归属的墓地. 当地的居民都是非常虔诚的基督徒,他们愿意提前为自己找一块合适墓地. ...
- [洛谷P1357] 花园
题目类型:状压\(DP\) -> 矩阵乘法 绝妙然而思维难度极其大的一道好题! 传送门:>Here< 题意:有一个环形花圃,可以种两种花:0或1. 要求任意相邻的\(M\)个花中1的 ...
- 洛谷P1357 花园(状态压缩 + 矩阵快速幂加速递推)
题目链接:传送门 题目: 题目描述 小L有一座环形花园,沿花园的顺时针方向,他把各个花圃编号为1~N(<=N<=^).他的环形花园每天都会换一个新花样,但他的花园都不外乎一个规则,任意相邻 ...
- 洛谷 P2672 推销员 解题报告
P2672 推销员 题目描述 阿明是一名推销员,他奉命到螺丝街推销他们公司的产品.螺丝街是一条死胡同,出口与入口是同一个,街道的一侧是围墙,另一侧是住户.螺丝街一共有N家住户,第i家住户到入口的距离为 ...
随机推荐
- C#_Switch语句的内部实现
Switch的C#内部实现 https://www.cnblogs.com/Interkey/p/3730432.html 在IL汇编语言中的Switch指令 -- 按照标号来进行跳转(和goto语句 ...
- Siki_Unity_3-3_背包系统
Unity 3-3 背包系统(基于UGUI) 任务1&2&3:演示.介绍.类图分析 背包面板.箱子面板.锻造合成面板.装备佩戴面板.商店面板等 面板的显示和隐藏.保存和加载.拾起物品. ...
- web小结
一.ajax 1.用于前端向服务器异步获取数据 json数组:可以直接通过数组下标获取到值 json对象:可以用“data.xx”获取到值 2.注意事项 同时请求两个ajax时,容易出现异常,第一个a ...
- Deep learning for visual understanding: A review 视觉理解中的深度学习:回顾 之一
Deep learning for visual understanding: A review 视觉理解中的深度学习:回顾 ABSTRACT: Deep learning algorithms ar ...
- Mysql DataPacketTooBigException异常处理
在本地上运行好好,然后发布到服务器上去, 总是报错,后来查了一下日志,得到了如下的错误日志: [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] Pa ...
- 实验1 熟悉Linux开发环境 实验报告
参见http://www.cnblogs.com/lhc-java/p/4970269.html
- Python写一个根据日期计算是星期几的模块
import datetimedef get_week_day(date): week_day = { 0: '星期一', 1: '星期二', 2: '星期三', 3: '星期四', 4: '星期五' ...
- 【Coursera】因子分析模型
一.协方差矩阵 协方差矩阵为对称矩阵. 在高斯分布中,方差越大,数据分布越分散,方差越小发,数据分布越集中. 在协方差矩阵中,假设矩阵为二维,若第二维的方差大于第一维的方差,则在图像上的体现就是:高斯 ...
- Alpha 冲刺报告(4/10)
Alpha 冲刺报告(4/10) 队名:洛基小队 峻雄(组长) 已完成:继续行动脚本的编写 明日计划:尽量完成角色的移动 剩余任务:物品背包交互代码 困难:具体编码进展比较缓慢 ----------- ...
- 简单实现wc.exe软件基本功能
简单实现wc.exe软件基本功能 软件需求分析: 一.基本功能 支持 -c 统计字符数(char count) 支持 -w 统计单词数(word count) 支持 -l 统计总行数(line ...