题目描述

现在有一个长度为n的随机排列,求它的最长上升子序列长度的期望。
为了避免精度误差,你只需要输出答案模998244353的余数。

输入

输入只包含一个正整数n。N<=28

输出

输出只包含一个非负整数,表示答案模998244353的余数。
可以证明,答案一定为有理数,设其为a/b(a、b为互质的整数),你输出的整数为x,
则你需要保证0≤x<998244353且a与bx模998244353同余。

样例输入

2

样例输出

499122178


题解

状压dp+打表

套路:对于排列问题,从左到右处理比较困难的话,考虑从小到大把数插入来处理。

对于一个确定的 $1\sim n$ 的排列,令 $f[i]$ 表示该排列以第 $i$ 个数结尾的最长上升子序列长度。令 $mx[i]$ 表示其前缀最大值,显然 $mx[i]\le mx[i+1]\le mx[i]+1$ ,根据这个我们可以状压前缀最大值的差分数组。

考虑在 $i$ 位置和 $i+1$ 位置加入一个新的最大数:这个数结尾的最长上升子序列长度一定为 $mx[i]+1$ ,因此把该位改成1,这个数后面的第一个1受其影响差分数组-1,把它改成0。

设 $dp[i][j]$ 表示 $1\sim i$ 的排列,$mx$ 的差分数组状压后为 $j$ 的方案数。那么答案就是 $\sum 每种状态的数目\times 每种状态的最长上升子序列长度$ 。

代码中我没有状压 $mx[1]-mx[0]$ ,因为一定是 $1$ 。这样答案就是 $\sum\limits_{i=0}^{2^{n-1}-1}dp[n][i]·cnt[i]$ ,$cnt[i]$ 表示 $i$ 种 $1$ 的数目。

最后乘以阶乘的逆元即为期望。

时间复杂度 $O(n^2·2^n)$ ,过不去。怎么办?打表...

打表程序:

#include <cstdio>
#include <cstring>
#define mod 998244353
typedef long long ll;
int f[2][134217735] , cnt[134217735];
ll pow(ll x , int y)
{
ll ans = 1;
while(y)
{
if(y & 1) ans = ans * x % mod;
x = x * x % mod , y >>= 1;
}
return ans;
}
int main()
{
int n , i , j , k , d , t , pos;
ll ans = 0 , fac = 1;
scanf("%d" , &n) , n -- ;
f[0][0] = 1;
for(d = i = 1 ; i <= n ; i ++ , d ^= 1)
{
memset(f[d] , 0 , sizeof(int) * (1 << i));
for(j = 0 ; j < (1 << (i - 1)) ; j ++ )
{
f[d][j << 1] = (f[d][j << 1] + f[d ^ 1][j]) % mod , pos = -1;
for(k = i - 1 ; ~k ; k -- )
{
t = ((j >> k) << (k + 1)) | (1 << k) | (j & ((1 << k) - 1));
if(j & (1 << k)) pos = k;
if(~pos) t ^= (1 << (pos + 1));
f[d][t] = (f[d][t] + f[d ^ 1][j]) % mod;
}
}
}
for(i = 1 ; i < (1 << n) ; i ++ ) cnt[i] = cnt[i - (i & -i)] + 1;
for(i = 0 ; i < (1 << n) ; i ++ ) ans = (ans + 1ll * f[n & 1][i] * (cnt[i] + 1)) % mod;
for(i = 1 ; i <= n + 1 ; i ++ ) fac = fac * i % mod;
printf("%lld\n" , ans * pow(fac , mod - 2) % mod);
return 0;
}

AC程序:

#include <cstdio>
int a[]={1,499122178,2,915057326,540715694,946945688,422867403,451091574,317868537,200489273, 976705134,705376344,662845575,331522185,228644314,262819964,686801362,495111839,947040129,414835038,696340671,749077581,301075008,314644758,102117126,819818153,273498600,267588741},n;
int main()
{
scanf("%d",&n);
printf("%d",a[n-1]);
return 0;
}

【bzoj5161】最长上升子序列 状压dp+打表的更多相关文章

  1. bzoj5161 最长上升子序列 状压DP(DP 套 DP) + 打表

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5161 题解 回顾一下以前用二分求 LIS 的方法:令 \(f[i]\) 表示长度为 \(i\) ...

  2. BZOJ.3591.最长上升子序列(状压DP)

    BZOJ 题意:给出\(1\sim n\)的一个排列的一个最长上升子序列,求原排列可能的种类数. \(n\leq 15\). \(n\)很小,参照HDU 4352这道题,我们直接把求\(LIS\)时的 ...

  3. BZOJ 5161: 最长上升子序列 状压dp+查分

    好神啊 ~ 打表程序: #include <cstdio> #include <cstring> #include <algorithm> #define N 14 ...

  4. 洛谷 P4484 - [BJWC2018]最长上升子序列(状压 dp+打表)

    洛谷题面传送门 首先看到 LIS 我们可以想到它的 \(\infty\) 种求法(bushi),但是对于此题而言,既然题目出这样一个数据范围,硬要暴搜过去也不太现实,因此我们需想到用某种奇奇怪怪的方式 ...

  5. hdu 4352 "XHXJ's LIS"(数位DP+状压DP+LIS)

    传送门 参考博文: [1]:http://www.voidcn.com/article/p-ehojgauy-ot.html 题解: 将数字num字符串化: 求[L,R]区间最长上升子序列长度为 K ...

  6. hdu4352-XHXJ's LIS状压DP+数位DP

    (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 题意:传送门  原题目描述在最下面.  在区间内把整数看成一个阿拉伯数字的集合,此集合中最长严格上升子序列的长度为k的个数. 思路: ...

  7. 「算法笔记」状压 DP

    一.关于状压 dp 为了规避不确定性,我们将需要枚举的东西放入状态.当不确定性太多的时候,我们就需要将它们压进较少的维数内. 常见的状态: 天生二进制(开关.选与不选.是否出现--) 爆搜出状态,给它 ...

  8. fzu2188 状压dp

    G - Simple String Problem Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & ...

  9. HDU 3001 状压DP

    有道状压题用了搜索被队友骂还能不能好好训练了,, hdu 3001 经典的状压dp 大概题意..有n个城市 m个道路  成了一个有向图.n<=10: 然后这个人想去旅行.有个超人开始可以把他扔到 ...

随机推荐

  1. BugPhobia开发篇章:Beta阶段第VIII次Scrum Meeting

    0x01 :Scrum Meeting基本摘要 Beta阶段第八次Scrum Meeting 敏捷开发起始时间 2015/12/22 00:00 A.M. 敏捷开发终止时间 2015/12/22 23 ...

  2. 每天学习SQL

    SELECT table_name FROM information_schema.tables WHERE table_schema='survey170227_main' AND table_na ...

  3. U 盘安装 CentOS的方法

    1. 刻录U盘 我使用的工具是 UltralISO 2. 打开ISO 3. 使用<启动>-<写入磁盘映像> 根据U盘的性能 可能好事 5min-15min左右 4.找到想要安装 ...

  4. Angular $cookieStore简单应用

    angular.module('cookieStoreExample', ['ngCookies']) .controller('ExampleController', ['$cookieStore' ...

  5. 软件工程_1st weeks

    本周为软件工程课的第一周,本周主要完成了三个工作:了解了github并使用.拜读了<构建之法>并开通了博客以及完成了四则运算的代码实现. 对于第一项工作github的安装和使用,花费了5个 ...

  6. python2 高级编程

    第一 正则表达式 1. 正则表达式意义 正则表达式是高级文本匹配模式,为搜索,匹配,替换提供了基础 2. 搜索与匹配的区别 搜索指在字符串任何部分查找 匹配指在字符串起始处查找 3. 编写正则表达式 ...

  7. ssh 将22端口换为其它 防火墙设置

    废话不多说,先通过当前的SSH端口(默认为:22)登陆. 1.修改配置文件:/etc/ssh/sshd_config ,找到 #port 22 2.先将Port 22 前面的 # 号去掉,并另起一行. ...

  8. 今天看到了一篇文档 app 测试内容记录下来

    1 APP测试基本流程 1.1流程图 1.2测试周期 测试周期可按项目的开发周期来确定测试时间,一般测试时间为两三周(即15个工作日),根据项目情况以及版本质量可适当缩短或延长测试时间.正式测试前先向 ...

  9. solr 字段设置不存储表示不会进行分词

    solr 字段设置不存储表示不会进行分词

  10. UVALive5876-Writings on the Wall-KMP

    有两段字符串,第一段的尾和第二段的头可能重合.问有多少种组合的可能. 需要理解一下next数组的意义. #include <cstdio> #include <cstring> ...