UOJ #214 合唱队形 (概率期望计数、DP、Min-Max容斥)

9个月的心头大恨终于切掉了!!!!
非常好的一道题,不知为何uoj上被点了70个差评。

题目链接: http://uoj.ac/problem/214

题目大意: 请自行阅读。

题解:

官方题解讲得相当清楚,这里补充一下自己的一些理解。

首先来看\(O(2^{n-m}\times poly(n,m))\)的做法。

一种理解方式是官方题解。

设\(s\)为总共的课程个数(\(n\)个字符串的总长度),\(p(S)\)表示结尾位置为集合\(S\)的串全部匹配一共需要完成多少个不同的课程。设\(f(t)\)表示\(t\)时刻整个过程没有终止的概率,\(prob(S,t)\)表示\(S\)集合结尾的串在\(t\)时刻或者之前已经完成匹配的概率。\(ans\)为答案。

\[ans=\sum^{+\inf}_{t=0} f(t)=\sum^{+\inf}_{t=0} \sum_{S, |S|\ge 0}(-1)^{|S|} prob(S,t)=\sum^{+\inf}_{t=0} \sum_{S,|S|\ge 0}(-1)^{|S|} \sum^{f(S)}_{i=0} (-1)^i{f(S)\choose i}(\frac{s-i}{s})^t\\ =\sum^{+\inf}_{t=0} \sum_{S,|S|\ge 0}(-1)^{|S|} \sum^{f(S)}_{i=1} (-1)^i{f(S)\choose i}(\frac{s-i}{s})^t\\ =\sum_{S,|S|\ge 0}(-1)^{|S|} \sum^{f(S)}_{i=0} (-1)^i{f(s)\choose i}\sum^{\inf}_{t=0}(\frac{s-i}{s})^t=\sum_{S,|S|\ge 0}(-1)^{|S|} \sum^{f(S)}_{i=0} (-1)^i{f(S)\choose i} \frac{s}{i}\]

计算即可。

其实还有另外一种理解方式。我们要求的是所有串匹配时间最小值的期望,根据Min-Max容斥,我们可以通过枚举子集转化成对每个子集求该子集内串匹配时间最大值的期望,然后转化成每一时刻没结束的概率。

然后来看更难的\(O(2^m\times poly(n,m))\)做法。

对于所有\(p(S)\)相同的\(S\), 其对答案的贡献没有区别。

因此对于所有\(k\),考虑计算\(p(S)=k\)的\(S\)的个数。

然后直接dp即可。

代码错误记录: 注意solution1如果\(n-m=16\)的话数组要开到\(2^{17}\).

代码

#include<cstdio>
#include<cstdlib>
#include<cstring>
#define llong long long
using namespace std;const int N = 30;
const int S = 26;
const int P = 998244353;
bool ok[N+3];
int f[N+3][S+3];
char str[N+3];
char a[N+3];
llong fact[2000003],finv[2000003],inv[2000003];
int cnt[(1<<17)+3];
int n,m,s;llong quickpow(llong x,llong y)
{llong cur = x,ret = 1ll;for(int i=0; y; i++){if(y&(1ll<<i)) {y-=(1ll<<i); ret = ret*cur%P;}cur = cur*cur%P;}return ret;
}
llong comb(llong x,llong y) {return x<0 || y<0 || x<y ? 0ll : fact[x]*finv[y]%P*finv[x-y]%P;}namespace Solution1
{int ff[N+3][S+3];llong ans;void solve(){ans = 0ll;for(int i=1; i<(1<<(n-m+1)); i++){llong cur = 0ll; bool gg = false;for(int j=0; j<=n-m; j++){if(i&(1<<j)){for(int k=0; k<m; k++){ff[j+k][a[k]-96] = true;if(f[j+k][a[k]-96]==false) {gg = true; break;}}if(gg==true) break;}}if(gg){for(int j=0; j<n; j++){for(int k=1; k<=S; k++){ff[j][k] = false;}}continue;}int num = 0;for(int j=0; j<n; j++){for(int k=1; k<=S; k++){if(ff[j][k]==true) {num++;}}}for(int j=1; j<=num; j++){llong tmp = (llong)s*inv[j]%P*comb(num,j)%P;if(!(j&1)) {cur = (cur+tmp)%P;}else {cur = (cur-tmp+P)%P;}}for(int j=0; j<n; j++){for(int k=1; k<=S; k++){ff[j][k] = false;}}if(cnt[i]&1) {ans = (ans-cur+P)%P;}else {ans = (ans+cur+P)%P;}}printf("%lld\n",ans);}
}namespace Solution2
{#define U ((1<<m)-1)const int M = 14;llong dp[N+3][(1<<M)+3][N*M+3];bool ff[N+3][M+3];void update(llong &x,llong y) {x = (x+y)%P;}void solve(){llong ans = 0ll;dp[m-1][0][0] = 1ll;for(int i=m-1; i<n; i++){for(int j=0; j<(1<<m); j++){bool okk = true;for(int k=0; k<m; k++) if((j&(1<<k)) && ok[i-k-1]==false) {okk = false; break;}if(!okk) continue;int p = 0;for(int k=0; k<m; k++){if(j&(1<<k)){for(int l=0; l<m; l++){ff[i-k-1-m+1+l][a[l]-96] = true;}}}for(int l=0; l<m; l++){if(ff[i-m+1+l][a[l]-96]==false){p++;}}for(int k=0; k<m; k++){if(j&(1<<k)){for(int l=0; l<m; l++){ff[i-k-1-m+1+l][a[l]-96] = false;}}}for(int k=0; k<=n*m; k++){if(dp[i][j][k]==0) continue;update(dp[i+1][(j<<1)&U][k],dp[i][j][k]);update(dp[i+1][(j<<1|1)&U][k+p],P-dp[i][j][k]);dp[i][j][k] = 0ll;}}}for(int i=1; i<=n*m; i++){llong coe = 0ll;for(int j=1; j<=i; j++){llong tmp = s*inv[j]%P*comb(i,j)%P;if(j&1) {coe = (coe-tmp+P)%P;}else {coe = (coe+tmp)%P;}}llong sum = 0ll;for(int j=0; j<(1<<m); j++){sum = (sum+dp[n][j][i])%P;dp[n][j][i] = 0ll;}ans = (ans+sum*coe)%P;}printf("%lld\n",ans);}
}int main()
{fact[0] = 1ll; for(int i=1; i<=2000000; i++) fact[i] = fact[i-1]*i%P;finv[2000000] = quickpow(fact[2000000],P-2); for(int i=1999999; i>=0; i--) finv[i] = finv[i+1]*(i+1)%P;for(int i=1; i<=2000000; i++) inv[i] = finv[i]*fact[i-1]%P;cnt[0] = 0; for(int i=1; i<(1<<17); i++) cnt[i] = cnt[i>>1]+(i&1);int T; scanf("%d",&T);while(T--){scanf("%d%d",&n,&m); s = 0;for(int i=0; i<n; i++){scanf("%s",str); int l = strlen(str);for(int j=0; j<l; j++){f[i][str[j]-96] = true; s++;}}scanf("%s",a); bool exist = false;for(int i=m-1; i<n; i++){ok[i] = true;for(int j=0; j<m; j++){if(f[i-m+1+j][a[j]-96]==false) {ok[i] = false; break;}}if(ok[i]) {exist = true;}}if(exist==false) {printf("-1\n");}else{if(n-m<=16){Solution1::solve();}else{Solution2::solve();}}for(int i=0; i<n; i++){for(int j=1; j<=S; j++) f[i][j] = false;ok[i] = false;}}return 0;
}

发表于 2019-06-15 11:55 suncongbo 阅读(...) 评论(...) 编辑 收藏

刷新评论刷新页面返回顶部

UOJ #214 合唱队形 (概率期望计数、DP、Min-Max容斥)相关推荐

  1. UOJ #214 [UNR #1]合唱队形 (概率期望计数、DP、Min-Max容斥)

    9个月的心头大恨终于切掉了!!!! 非常好的一道题,不知为何uoj上被点了70个差评. 题目链接: http://uoj.ac/problem/214 题目大意: 请自行阅读. 题解: 官方题解讲得相 ...

  2. P3175 [HAOI2015]按位或(Min - Max容斥,FMT,概率期望,全网最清晰的题解!)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Weblink https://www.luogu.com.cn/problem/P3175 Prob ...

  3. UOJ#449. 【集训队作业2018】喂鸽子 min-max容斥,FFT

    原文链接www.cnblogs.com/zhouzhendong/p/UOJ449.html 题解 设 f(i) 表示给 i 只鸽子喂食使得至少一只鸽子被喂饱的期望次数,先 min-max容斥 一下. ...

  4. Codeforces 1264C/1265E Beautiful Mirrors with queries (概率期望、DP)

    题目链接 http://codeforces.com/contest/1264/problem/C 题解 吐槽:为什么我赛后看cf的题就经常1h内做出Div.1 C, 一打cf就动不动AB题不会啊-- ...

  5. [概率期望][树形DP][LCA]JZOJ 5814 树

    Description 梦游中的你来到了一棵 N 个节点的树上. 你一共做了 Q 个梦, 每个梦需要你从点 u 走到 点 v 之后才能苏醒, 由于你正在梦游, 所以每到一个节点后,你会在它连出去的边中 ...

  6. 【DP】【容斥】Nice to Meet You(AT3634)

    正题 luogu AT3634 题目大意 给你一个图,让你给图上的边定方向,问1,2两个点可以到同一个点的方案数 解题思路 直接求可以到同一个点不好求,可以用总方案数减去不合法方案数,即到不了同一个点 ...

  7. loj#2542 [PKUWC2018]随机游走 (概率期望、组合数学、子集和变换、Min-Max容斥)

    loj#2542 [PKUWC2018]随机游走 (概率期望.组合数学.子集和变换.Min-Max容斥) 很好很有趣很神仙的题! 题目链接: https://loj.ac/problem/2542 题 ...

  8. LOJ #2542 [PKUWC2018]随机游走 (概率期望、组合数学、子集和变换、Min-Max容斥)

    很好很有趣很神仙的题! 题目链接: https://loj.ac/problem/2542 题意: 请自行阅读 题解首先我们显然要求的是几个随机变量的最大值的期望(不是期望的最大值),然后这玩意很难求 ...

  9. P4707-重返现世【dp,数学期望,扩展min-max容斥】

    正题 题目链接:https://www.luogu.com.cn/problem/P4707 题目大意 nnn个物品,每次生成一种物品,第iii个被生成的概率是pim\frac{p_i}{m}mpi​ ...

最新文章

  1. shell判断数字大小_shell! shell! shell!
  2. 容器 vector :为何要有reserve
  3. C++条件编译:#ifdef
  4. discuz 二次开发文章
  5. 查看Centos7系统参数和机器参数
  6. Java多线程之Synchronized和Lock的区别
  7. celery 学习笔记定时任务和异步任务
  8. powercfg -h off_万代 S.H.Figuarts「假面骑士01 金属腾蝗形态」
  9. 学习笔记(03):MySQL数据库运维与管理-01-mysql通用日志与错误日志
  10. ubuntu Django mysqlclient的问题
  11. 《Linux编程》学习笔记 ·002【Linux常用工具GCC、GDB、Make】
  12. 邮件服务器篇:杀毒引擎选择论据
  13. JAVA基础编程——简介
  14. 飞行堡垒FX80GM热键无反应与触摸板无法使用
  15. shell脚本中source和expert的简单理解
  16. 密钥管理——密钥生命周期管理
  17. 洛谷 P4094 [HEOI2016/TJOI2016]字符串 后缀数组+二分+主席树
  18. 有道云笔记、石墨笔记、 Effie …评论家怎么选?
  19. Ubuntu下安装XAMPP
  20. HTTP协议详解1----请求状态与响应

热门文章

  1. 5 Android数据存储 任务二 应用程序数据文件夹里的文件读写 ,
  2. sqlserver中编写自定义函数中的返回值问题
  3. socket使用多进程实现并发的服务器
  4. 【CyberSecurityLearning 48】PHP Cookie 和 SESSION
  5. git reset 命令详解(二)—— Git 学习笔记 08
  6. Spring事务传播机制和隔离级别
  7. STM32开发 -- CRC校验码
  8. hdu1272(简单并查集)
  9. 九余定理(hdu1013)
  10. stl-unique()函数去重