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. Java高并发--消息队列

    Java高并发--消息队列 主要是学习慕课网实战视频<Java并发编程入门与高并发面试>的笔记 举个例子:在购物商城下单后,希望购买者能收到短信或者邮件通知.有一种做法时在下单逻辑执行后调 ...

  2. MyBatis:CRUD功能

    在前面已经自动生成了mapper和pojo,接下来我们实现mybatis的CRUD功能,先新建service.controller层的方法. 这里的sid是一个开源的id生成类,写完后,我们还需要在启 ...

  3. Java学习笔记之——Object类

    所有类的祖先 如果一个类没有显式继承,则继承Object 每一个类都直接或间接的是Object的子类 相关API: protected Objectclone() 创建并返回此对象的副本. boole ...

  4. 【Spring】17、spring cache 与redis缓存整合

    spring cache,基本能够满足一般应用对缓存的需求,但现实总是很复杂,当你的用户量上去或者性能跟不上,总需要进行扩展,这个时候你或许对其提供的内存缓存不满意了,因为其不支持高可用性,也不具备持 ...

  5. regression and anova

    regression一般是统计学的回归回归,研究一个随机变量Y对另一个(X)或一组(X1,X2,-,Xk)变量的相依关系的统计分析方法.研究一 个或多个随机变量Y1 ,Y2 ,-,Yi与另一些变量X1 ...

  6. Html5页面内使用JSON动画的实现

    有一天我们的UI设计师找到我说,要把页面中我自己用程序写的动画,换成他们给的json动画,原因是有的动画很复杂,自己写起来达不到他们的预期效果(写到这里我突然想到一个问题,这么复杂的动画为什么不使用g ...

  7. bootstrap日期控件(双日期、清空等问题解决)

    bootstrap以它优美的外观和丰富的组件,使它成为目前最流行的前端框架.在项目开发中,我们使用它的日期控件确实遇到了一些问题: 1.日期控件后面两个图标点击触发失效 2.双日期关联问题 3.双日期 ...

  8. Loadrunner 脚本开发-利用loadrunner开发Windows Sockets协议脚本

    脚本开发-利用loadrunner开发Windows Sockets协议脚本 by:授客 QQ:1033553122 欢迎加入软件性能测试交流QQ群:7156436 实践举例 Socket服务端简单实 ...

  9. leetcode-67.二进制求和

    leetcode-67.二进制求和 Points 数组 数学 题意 给定两个二进制字符串,返回他们的和(用二进制表示). 输入为非空字符串且只包含数字 1 和 0. 示例 1: 输入: a = &qu ...

  10. WordCount作业修改

    WordCount作业修改 github地址 需求说明 基本需求 功能说明 PSP 代码实现 字符总数查询 单词数查询 行数查询 总结 一.需求说明 1.基本需求 WordCount的需求可以概括为: ...