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 花园 解题报告的更多相关文章

  1. 题解:洛谷P1357 花园

    题解:洛谷P1357 花园 Description 小 L 有一座环形花园,沿花园的顺时针方向,他把各个花圃编号为 \(1∼n\).花园 \(1\) 和 \(n\) 是相邻的. 他的环形花园每天都会换 ...

  2. 洛谷 P2058 海港 解题报告

    P2058 海港 题目描述 小K是一个海港的海关工作人员,每天都有许多船只到达海港,船上通常有很多来自不同国家的乘客. 小K对这些到达海港的船只非常感兴趣,他按照时间记录下了到达海港的每一艘船只情况: ...

  3. 洛谷 P3956 棋盘 解题报告

    P3956 棋盘 题目描述 有一个\(m×m\)的棋盘,棋盘上每一个格子可能是红色.黄色或没有任何颜色的.你现在要从棋盘的最左上角走到棋盘的最右下角. 任何一个时刻,你所站在的位置必须是有颜色的(不能 ...

  4. 洛谷 P1979 华容道 解题报告

    P1979 华容道 题目描述 小\(B\)最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时 ...

  5. BZOJ 3545 / 洛谷 P4197 Peaks 解题报告

    P4197 Peaks 题目描述 在\(\text{Bytemountains}\)有\(N\)座山峰,每座山峰有他的高度\(h_i\).有些山峰之间有双向道路相连,共\(M\)条路径,每条路径有一个 ...

  6. 虔诚的墓主人(BZOJ1227)(洛谷P2154)解题报告

    题目描述 小W是一片新造公墓的管理人.公墓可以看成一块N×M的矩形,矩形的每个格点,要么种着一棵常青树,要么是一块还没有归属的墓地. 当地的居民都是非常虔诚的基督徒,他们愿意提前为自己找一块合适墓地. ...

  7. [洛谷P1357] 花园

    题目类型:状压\(DP\) -> 矩阵乘法 绝妙然而思维难度极其大的一道好题! 传送门:>Here< 题意:有一个环形花圃,可以种两种花:0或1. 要求任意相邻的\(M\)个花中1的 ...

  8. 洛谷P1357 花园(状态压缩 + 矩阵快速幂加速递推)

    题目链接:传送门 题目: 题目描述 小L有一座环形花园,沿花园的顺时针方向,他把各个花圃编号为1~N(<=N<=^).他的环形花园每天都会换一个新花样,但他的花园都不外乎一个规则,任意相邻 ...

  9. 洛谷 P2672 推销员 解题报告

    P2672 推销员 题目描述 阿明是一名推销员,他奉命到螺丝街推销他们公司的产品.螺丝街是一条死胡同,出口与入口是同一个,街道的一侧是围墙,另一侧是住户.螺丝街一共有N家住户,第i家住户到入口的距离为 ...

随机推荐

  1. move.js运动插件

    move.js 运动插件是一款针对元素动画效果的插件.可以运用此插件制作出各类元素效果. 插件GitHub地址:https://github.com/visionmedia/move.js 下面整理学 ...

  2. Spring入门学习笔记(3)——事件处理类

    目录 Spring中的事件处理 Spring内建事件 监听Context事件 Example 自定义Spring事件 Spring中的事件处理 ApplicationContext 是Spring的核 ...

  3. python—索引与切片总结

    python中索引与切片的熟练掌握对于字符串的操作很有帮助,梳理如下: (1)索引 S = 'hello world' 1)正向索引 正向索引从0开始,向右依次递增. 2)反向索引 反向索引从-1开始 ...

  4. 点斜杠 & 如何查看linux程序安装位置 dpkg -L yyy

    方法1: sudo find / -name ssh 方法2: Ubuntu下 看应用程序安装路径的方法 ubuntu下dpkg -L xxx看应用程序安装路径 1.点斜杠 “./”就代表在当前目录下 ...

  5. nginx 在ubuntu上使用笔记(绑定域名)

    1. 重启nginx的两个语句: sudo service nginx restart sudo nginx -s reload 2. nginx配置文件路径: etc/nginx/ 尤其是 site ...

  6. TeamWork#3,Week5,Scrum Meeting 11.9

    由于经验不足和储备知识不够,最近我们的项目遇到了一些技术问题,需要对项目进行重新计划.我们总结了经验教训,找出了问题所在,明确了要补充的知识,加紧学习,将会在一周之内解决相关问题. 成员 已完成 待完 ...

  7. Daily Scrum meeting 2015.11.9

    今天主要完成项目最后的调试工作及二轮迭代的准备 下面是今天的Task统计: Member Today’s Task Tomorrow’s Task 江昊 今天,完成前端界面调整,网站发布 调试 杨墨犁 ...

  8. 安卓端通过http对Mysql进行增删改查

    各类it学习视频,大家都可以看看哦!我自己本人都是通过这些来学习it只知识的! 下面是视频链接转自:http://www.cnblogs.com/yzxk/p/4749440.html Android ...

  9. 《Spring1之第六次站立会议》

    <第六次站立会议> 昨天:向小伙伴们请教了我代码的错误的解决方法以及对TCP/IP协议进行了相关的了解. 今天:我把自己项目工程里的服务器端界面进行了优化和完善. 遇到的问题:觉得做的界面 ...

  10. DPDK L2fwd 源码阅读

    代码部分 /* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2010-2016 Intel Corporation */ #include ...