Loj #6069. 「2017 山东一轮集训 Day4」塔

题目描述

现在有一条 $ [1, l] $ 的数轴,要在上面造 $ n $ 座塔,每座塔的坐标要两两不同,且为整点。

塔有编号,且每座塔都有高度,对于编号为 $ i $ 座塔,其高度为 $ i $。对于一座塔,需要满足它与前面以及后面的塔的距离大于等于自身高度(不存在则没有限制)。问有多少建造方案。答案对 $ m $ 取模。

塔不要求按编号为顺序建造。

输入格式

一行三个整数 $ n, l, m $。

输出格式

输出一个整数,代表答案对 $ m $ 取模的值。

样例

样例输入

3 9 17

样例输出

15

数据范围与提示

对于 $ 10% $ 的数据,$ n \leq 10; l \leq 25 $;

对于 $ 30% $ 的数据,$ n \leq 20 $;

对于 $ 50% $ 的数据,$ n \leq 50 $;

对于 $ 70% $ 的数据,$ l \leq 105 $;

对于 $ 100% $ 的数据,$ n \leq 100; 1 \leq l \leq 10 ^ 9; 1 \leq m \leq 10 ^ 9 $。

首先我们得到一个排列\(P\),设\(S=\sum max\{P_{i-1},P_i\}\),\(S+1\)就是这个排列紧密地排在一起时的长度。还剩下了\(l-(S+1)\)个格子, 我们就将这些格子放在相邻的元素之间,方案数为\(\binom{l-S-1+n}{n}\)。

所以我们要先求出\(S=k\)的排列个数。

设\(f_{i,j,k}\)表示放了前\(i\)个数,整个排列分为了\(j\)个联通块,排列的总长度为\(k\)的方案数。因为我们设从小到大放数,所以如果一个数\(i\),它的左侧是空的或者会有另一个数,则不会对\(S\)有贡献,右侧同理。

转移的时候就考虑第\(i\)个数与多少个联通块相连(最多两个),就可以知道第\(i\)个数对\(S\)的贡献。

接下来考虑处理组合数。因为\(n\)比较小,所以对于每个\(L\),我们只保留\(\binom{L}{0..n}\)。用矩阵快速幂处理即可。

代码:

#include<bits/stdc++.h>
#define ll long long
#define N 105 using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;} int n,l;
ll mod;
int f[N][N*N],g[N][N*N];
int per[N*N]; struct matrix {
int a[105][105];
void Init() {
memset(a,0,sizeof(a));
}
}F,G; int Mod(int a) {return a<mod?a:a-mod;}
matrix operator *(const matrix &x,const matrix &y) {
static matrix tem;
tem.Init();
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
for(int k=0;k<=n;k++)
tem.a[i][j]=Mod( tem.a[i][j]+1ll*x.a[i][k]*y.a[k][j]%mod);
return tem;
} matrix ksm(matrix g,int x) {
matrix ans;
ans.Init();
for(int i=0;i<=n;i++) ans.a[i][i]=1;
for(;x;x>>=1,g=g*g)
if(x&1) ans=ans*g;
return ans;
} int main() {
n=Get(),l=Get(),mod=Get();
int sum=0;
f[1][0]=1;
sum=2;
for(int i=2;i<=n;i++) {
for(int j=1;j<i;j++) memset(g[j],0,sizeof(g[j]));
for(int j=1;j<=i;j++) {
for(int k=0;k<=sum;k++) {
if(!f[j][k]) continue ;
g[j+1][k]=Mod(g[j+1][k]+1ll*f[j][k]*(j+1)%mod);
g[j][k+i]=Mod(g[j][k+i]+1ll*f[j][k]*j*2%mod);
if(j>1) g[j-1][k+2*i]=Mod(g[j-1][k+2*i]+1ll*f[j][k]*(j-1)%mod);
}
}
memcpy(f,g,sizeof(f));
sum+=2*i;
}
for(int i=0;i<sum;i++) per[i+1]=f[1][i];
int mx=0;
for(int i=0;i<sum;i++) if(per[i]) mx=i;
mx=min(mx,l+n);
F.a[0][0]=1;
for(int i=0;i<=n;i++) {
G.a[i][i]=1;
if(i) G.a[i-1][i]=1;
}
F=F*ksm(G,l-mx+n);
ll ans=0;
for(int i=mx;i>=0;i--) {
(ans+=1ll*per[i]*F.a[0][n])%=mod;
for(int j=n;j>0;j--) {
(F.a[0][j]+=F.a[0][j-1])%=mod;
}
}
cout<<ans;
return 0;
}

Loj #6069. 「2017 山东一轮集训 Day4」塔的更多相关文章

  1. Loj 6068. 「2017 山东一轮集训 Day4」棋盘

    Loj 6068. 「2017 山东一轮集训 Day4」棋盘 题目描述 给定一个 $ n \times n $ 的棋盘,棋盘上每个位置要么为空要么为障碍.定义棋盘上两个位置 $ (x, y),(u, ...

  2. [LOJ#6068]. 「2017 山东一轮集训 Day4」棋盘[费用流]

    题意 题目链接 分析 考虑每个棋子对对应的横向纵向的极大区间的影响:记之前这个区间中的点数为 \(x\) ,那么此次多配对的数量即 \(x\) . 考虑费用流,\(S\rightarrow 横向区间 ...

  3. LOJ 6068「2017 山东一轮集训 Day4」棋盘

    题意 一个 \(n\times n\) 的棋盘上面有若干障碍物. 定义两个棋子可以互相攻击当且仅当这两个棋子的横坐标或纵坐标相等而且中间不能隔着障碍物.(可以隔棋子) 有 \(q\) 次询问,每次询问 ...

  4. Loj #6073.「2017 山东一轮集训 Day5」距离

    Loj #6073.「2017 山东一轮集训 Day5」距离 Description 给定一棵 \(n\) 个点的边带权的树,以及一个排列$ p\(,有\)q $个询问,给定点 \(u, v, k\) ...

  5. loj6068. 「2017 山东一轮集训 Day4」棋盘 二分图,网络流

    loj6068. 「2017 山东一轮集训 Day4」棋盘 链接 https://loj.ac/problem/6068 思路 上来没头绪,后来套算法,套了个网络流 经典二分图 左边横,右边列 先重新 ...

  6. LOJ #6074. 「2017 山东一轮集训 Day6」子序列

    #6074. 「2017 山东一轮集训 Day6」子序列 链接 分析: 首先设f[i][j]为到第i个点,结尾字符是j的方案数,这个j一定是从i往前走,第一个出现的j,因为这个j可以代替掉前面所有j. ...

  7. loj #6077. 「2017 山东一轮集训 Day7」逆序对

    #6077. 「2017 山东一轮集训 Day7」逆序对   题目描述 给定 n,k n, kn,k,请求出长度为 n nn 的逆序对数恰好为 k kk 的排列的个数.答案对 109+7 10 ^ 9 ...

  8. LOJ #6119. 「2017 山东二轮集训 Day7」国王

    Description 在某个神奇的大陆上,有一个国家,这片大陆的所有城市间的道路网可以看做是一棵树,每个城市要么是工业城市,要么是农业城市,这个国家的人认为一条路径是 exciting 的,当且仅当 ...

  9. loj#6073. 「2017 山东一轮集训 Day5」距离(树链剖分 主席树)

    题意 题目链接 Sol 首先对询问差分一下,我们就只需要统计\(u, v, lca(u, v), fa[lca(u, v)]\)到根的路径的贡献. 再把每个点与\(k\)的lca的距离差分一下,则只需 ...

随机推荐

  1. SVN 安装后右键出现点击鼠标右键弹出错误提示:CrashHandler initialization error

    SVN 安装后右键出现点击鼠标右键弹出错误提示:CrashHandler initialization error 原因是目标文件夹中缺少SendRpt.exe文件 解决方案:找svn是好的的同事将b ...

  2. [日常]nginx与网络事件模型

    Nginx 的特点: 1.处理静态文件 2.反向代理加速 3.fastCGI,简单的负载均衡和容错 4.模块化的结构 5.分阶段资源分配技术,使得它的 CPU 与内存占用率非常低,保持 10,000 ...

  3. 22.QT-QXmlStreamReader解析,QXmlStreamWriter写入

    XML介绍 XML 用于存储数据,数据的形式类似于树结构(参考: http://www.runoob.com/xml/) 示例如下 <?xml version="1.0" e ...

  4. Java学习笔记之——枚举类

    枚举可以限定类的值只是有限个,例如:星期,只有星期一到星期天 语法案例:

  5. python基础学习(八)元组

    元组的定义 Tuple(元组)与列表类似,不同之处在于元组的 元素不能修改 元组 表示多个元素组成的序列 元组 在 Python 开发中,有特定的应用场景 用于存储 一串 信息,数据 之间使用 , 分 ...

  6. Spring的xml解析原理分析【转载】

    一:前言 二:spring的配置文件 三:依赖的第三方库.使用技术.代码布局 四:Document实现 五:获取Element的实现 六:解析Element元素 七:Bean创造器 八:Ioc容器的创 ...

  7. 13 ,CSS 入门基础,行内排版内嵌式排版和外部排版样式

    1.认识 CSS 2.传统 HTML 设计网页版面的缺点 3.CSS 的特点 4.CSS 的排版样式 13.1 认识CSS CSS的英文全名是 Cascading Style Sheets,中文可翻译 ...

  8. 9;XHTML 多媒体

    1.FLASH 动画的插入 2.MP3 及 WMV 视频的插入 3.网络流媒体视频的插入 使用 Web 如此流行的原因之一是可以再网页上加入图像.声音.动画和电影文件.虽然 过去对这些文件大小的限制局 ...

  9. 前端常见算法的JS实现

    1.冒泡排序 function bubbleSort(arr){ var i = 0, j = 0; for(i=1; i<arr.length; i++){ for(j=0; j<=ar ...

  10. Ubuntu、deepin 支持 yum

    1,首先检测是否安装了build-essential程序包 sudo apt-get install build-essential 2,安装 yum sudo apt-get yum 3,检测是否安 ...