Loj #6069. 「2017 山东一轮集训 Day4」塔
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」塔的更多相关文章
- Loj 6068. 「2017 山东一轮集训 Day4」棋盘
Loj 6068. 「2017 山东一轮集训 Day4」棋盘 题目描述 给定一个 $ n \times n $ 的棋盘,棋盘上每个位置要么为空要么为障碍.定义棋盘上两个位置 $ (x, y),(u, ...
- [LOJ#6068]. 「2017 山东一轮集训 Day4」棋盘[费用流]
题意 题目链接 分析 考虑每个棋子对对应的横向纵向的极大区间的影响:记之前这个区间中的点数为 \(x\) ,那么此次多配对的数量即 \(x\) . 考虑费用流,\(S\rightarrow 横向区间 ...
- LOJ 6068「2017 山东一轮集训 Day4」棋盘
题意 一个 \(n\times n\) 的棋盘上面有若干障碍物. 定义两个棋子可以互相攻击当且仅当这两个棋子的横坐标或纵坐标相等而且中间不能隔着障碍物.(可以隔棋子) 有 \(q\) 次询问,每次询问 ...
- Loj #6073.「2017 山东一轮集训 Day5」距离
Loj #6073.「2017 山东一轮集训 Day5」距离 Description 给定一棵 \(n\) 个点的边带权的树,以及一个排列$ p\(,有\)q $个询问,给定点 \(u, v, k\) ...
- loj6068. 「2017 山东一轮集训 Day4」棋盘 二分图,网络流
loj6068. 「2017 山东一轮集训 Day4」棋盘 链接 https://loj.ac/problem/6068 思路 上来没头绪,后来套算法,套了个网络流 经典二分图 左边横,右边列 先重新 ...
- LOJ #6074. 「2017 山东一轮集训 Day6」子序列
#6074. 「2017 山东一轮集训 Day6」子序列 链接 分析: 首先设f[i][j]为到第i个点,结尾字符是j的方案数,这个j一定是从i往前走,第一个出现的j,因为这个j可以代替掉前面所有j. ...
- loj #6077. 「2017 山东一轮集训 Day7」逆序对
#6077. 「2017 山东一轮集训 Day7」逆序对 题目描述 给定 n,k n, kn,k,请求出长度为 n nn 的逆序对数恰好为 k kk 的排列的个数.答案对 109+7 10 ^ 9 ...
- LOJ #6119. 「2017 山东二轮集训 Day7」国王
Description 在某个神奇的大陆上,有一个国家,这片大陆的所有城市间的道路网可以看做是一棵树,每个城市要么是工业城市,要么是农业城市,这个国家的人认为一条路径是 exciting 的,当且仅当 ...
- loj#6073. 「2017 山东一轮集训 Day5」距离(树链剖分 主席树)
题意 题目链接 Sol 首先对询问差分一下,我们就只需要统计\(u, v, lca(u, v), fa[lca(u, v)]\)到根的路径的贡献. 再把每个点与\(k\)的lca的距离差分一下,则只需 ...
随机推荐
- Cookie 用法
//Cookie:是一个客户端状态保持机制,(网站的数据是存在客户端),与隐藏域与ViewState对象都属于这种客户端状态保持,Cookie中存储的是关于网站相关的文本字符串数据.Cookie的存储 ...
- 去重分页sql语句
---恢复内容开始--- SELECT [TAGNAME] FROM ( SELECT tagname,ROW_NUMBER() OVER(order by tagname) AS RowNumber ...
- 解决org.hibernate.exception.SQLGrammarException:could not insert
今天在使用hibernate搭建项目时碰到了这个错误,找了好半天没能发现错误的原因, 上网求助了一下 发现出现这个bug的原因是因为数据表使用了数据库的关键字(保留字) 然后检查了一下,发现字段名称都 ...
- 远程连接centos7 上的mysql报(ERROR 2003 (HY000): Can't connect to MySQL server on '168.x.x.x' (10060) )
1.MySQL端口 因为上一篇文章我就已经给MySQL新建了一新用户,且赋予了远程连接数据库的所有权限(GRANT ALL PRIVILEGES ON *.* TO 'newuser' @ '%' I ...
- 13 ,CSS 入门基础,行内排版内嵌式排版和外部排版样式
1.认识 CSS 2.传统 HTML 设计网页版面的缺点 3.CSS 的特点 4.CSS 的排版样式 13.1 认识CSS CSS的英文全名是 Cascading Style Sheets,中文可翻译 ...
- Javascript动态引用CSS文件的2种方法介绍
最近做一个项目,需要javascript动态插入样式,结果以前的方法失效了!查了2个小时的原因竟然是自己手贱,这个最后再说! javascript插入样式在前端开发中应用比较广泛,特别是在修改前端表现 ...
- C# SqlBulkCopy类批量导入 测试
一.功能说明 1.可以选择,只导入部分列,或者导入全部列. 2.导入速度的确比一般sql要快. 3.不用写sql语句 ----------------------------------------- ...
- Spider-four
计算机速度比较: CPU -> 寄存器 -> 缓存L1/L2/L3 -> 内存 -> 硬盘 -> 网卡 -> BIOS LMAP: Linux + MySQL + ...
- Spider-three
一.selenium from selenium import webdriver driver = webdriver.Chrome() # 创建一个chrome浏览器控制对象#driver = w ...
- ubuntu12.0.4开启root用户登陆
1.命令:sudo passwd root 为root分配密码,按提示进行设置就好. 2.打开终端,输入以下命令: sudo -s 进入root账户下: cd /etc/lightdm g ...