news 2026/6/9 23:13:03

UVa 10835 Playing with Coins

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
UVa 10835 Playing with Coins

问题描述

Jack \texttt{Jack}JackJill \texttt{Jill}Jill对抛硬币生成的序列模式感兴趣。给定抛硬币次数N NNK KK个禁止的子模式,我们需要计算不包含任何禁止子模式的序列的概率。

输入

  • 每个测试用例包含两个整数N NNK KK1 ≤ N ≤ 50 1 \leq N \leq 501N500 ≤ K ≤ 50 0 \leq K \leq 500K50
  • 接下来K KK行,每行是一个由字符HT组成的子模式
  • 所有子模式长度相同,且长度不超过10 1010
  • 输入以N = K = 0 N = K = 0N=K=0结束

输出

  • 对于每个测试用例,输出概率的最简分数形式a / b a/ba/b,如果概率为0 00则输出0

解题思路

1. 问题转化

这是一个典型的字符串模式匹配问题。我们需要统计长度为N NNH/T序列中,不包含任何给定子模式的序列数量。

总序列数为2 N 2^N2N,因此:
概率 = 安全序列数 2 N \text{概率} = \frac{\text{安全序列数}}{2^N}概率=2N安全序列数

2. 关键观察

  1. 子模式长度固定:所有禁止子模式长度相同,设为M MMM ≤ 10 M \leq 10M10
  2. 状态表示:对于模式匹配问题,我们只需要关心序列的最后M MM个字符,因为更早的字符不会影响是否匹配长度为M MM的子模式
  3. 位掩码表示:可以用二进制位表示序列:
    • H→ 1
    • T→ 0
    • 长度为M MM的子模式可以表示为一个M MM位二进制数

3. 算法设计

状态定义

d p [ length ] [ mask ] dp[\texttt{length}][\texttt{mask}]dp[length][mask]表示:

  • 当前序列长度为length \texttt{length}length
  • 序列的最后M MM个字符(不足M MM位时用前导零补齐)的位掩码为mask \texttt{mask}mask
  • 值为满足以上条件且不包含任何禁止子模式的序列数量
状态转移

从当前状态( length , mask ) (\texttt{length}, \texttt{mask})(length,mask)可以:

  1. 添加一个H(二进制 1)
  2. 添加一个T(二进制 0)

新的掩码计算方式:
newMask = ( ( mask ≪ 1 ) & ( ( 1 ≪ M ) − 1 ) ) ∣ bit \texttt{newMask} = ((\texttt{mask} \ll 1) \& ((1 \ll M) - 1)) \mid \texttt{bit}newMask=((mask1)&((1M)1))bit
其中:

  • << 1表示左移一位,相当于去掉最旧的字符
  • & ((1 << M) - 1)确保掩码保持在M MM
  • | bit添加新字符(0 001 11
禁止模式检查

只有当序列长度≥ M − 1 \geq M-1M1时,才需要检查新的掩码是否在禁止集合中:

  • 如果newMask \texttt{newMask}newMask在禁止集合中,则跳过该转移
  • 否则,继续递归
边界条件
  • length = N \texttt{length} = Nlength=N时,找到一个安全序列,返回1 11
  • 使用记忆化搜索避免重复计算

4. 特殊情况处理

  1. K = 0 K = 0K=0:没有禁止模式,所有2 N 2^N2N个序列都安全,概率为1 11
  2. M > N M > NM>N:禁止模式长度大于序列长度,不可能出现该模式,所有序列都安全,概率为1 11
  3. 否则:使用动态规划计算安全序列数

5. 概率计算

设安全序列数为safe \texttt{safe}safe,总序列数为2 N 2^N2N,则:
概率 = safe 2 N \text{概率} = \frac{\texttt{safe}}{2^N}概率=2Nsafe
需要化简为最简分数,使用gcd ⁡ \gcdgcd函数求最大公约数。

算法复杂度分析

  • 状态数O ( N × 2 M ) O(N \times 2^M)O(N×2M),其中M ≤ 10 M \leq 10M10
  • 每个状态转移O ( 1 ) O(1)O(1)
  • 总复杂度O ( N × 2 M ) O(N \times 2^M)O(N×2M),对于N ≤ 50 N \leq 50N50完全可行
  • 空间复杂度O ( N × 2 M ) O(N \times 2^M)O(N×2M)

代码实现

// Playing with Coins// UVa ID: 10835// Verdict: Accepted// Submission Date: 2025-12-22// UVa Run Time: 0.020s//// 版权所有(C)2025,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;set<int>forbidden;// 存储禁止模式的位掩码intN,K,M;// N:总长度, K:禁止模式数, M:模式长度longlongdp[64][1024];// dp[i][j]: 长度i,最后M位的掩码为j// 记忆化搜索longlongdfs(intlength,intmask){if(length>=N)return1LL;// 找到一个安全序列if(~dp[length][mask])returndp[length][mask];// 记忆化longlong&r=dp[length][mask];r=0;// 尝试添加 H(1) 或 T(0)for(inti=0;i<=1;i++){intnextMask=(((mask<<1)&((1<<M)-1)))|i;// 只有长度足够时才检查禁止模式if(length<M-1||!forbidden.count(nextMask))r+=dfs(length+1,nextMask);}returnr;}intmain(){intcaseNo=1;while(cin>>N>>K,N){cout<<"Case "<<caseNo++<<": ";forbidden.clear();// 读入禁止模式并转换为位掩码for(inti=0;i<K;i++){string pattern;cin>>pattern;M=pattern.length();intmask=0;for(autop:pattern)mask=(mask<<1)|(p=='H'?1:0);forbidden.insert(mask);}// 特殊情况处理:没有禁止模式或模式长度大于序列长度if(K==0||M>N){cout<<"1/1\n";continue;}// 动态规划计算安全序列数memset(dp,-1,sizeofdp);longlongsafe=dfs(0,0);// 输出结果if(safe==0)cout<<"0\n";else{longlongtotal=1LL<<N;longlongg=__gcd(safe,total);cout<<safe/g<<'/'<<total/g<<'\n';}}return0;}

样例解析

样例输入

3 1 HH 3 1 HT 3 2 T H 0 0

样例输出

Case 1: 5/8 Case 2: 1/2 Case 3: 0

解释

Case 1 \texttt{Case 1}Case 1

  • N = 3 N = 3N=3,禁止模式:HH(二进制 11)
  • 包含HH的序列:HHH,HHT,THH(3个)
  • 安全序列:8 − 3 = 5 8 - 3 = 583=5
  • 概率:5 / 8 5/85/8

Case 2 \texttt{Case 2}Case 2

  • 禁止模式:HT(二进制 10)
  • 包含HT的序列:HHT,HTH,HTT,THT(4个)
  • 安全序列:4 44
  • 概率:4 / 8 = 1 / 2 4/8 = 1/24/8=1/2

Case 3 \texttt{Case 3}Case 3

  • 禁止模式:T(0)和H(1)
  • 所有序列都至少包含一个TH
  • 安全序列:0 00
  • 概率:0 00

总结

本题通过位掩码 + 动态规划(记忆化搜索)的方法,高效地解决了模式匹配计数问题。关键点在于:

  1. 用二进制位表示字符序列,简化操作
  2. 只需维护最后M MM个字符的状态
  3. 记忆化搜索避免重复计算
  4. 特殊情况的预处理
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/8 13:39:34

谷歌浏览器翻译插件的使用

网页中显示了英文&#xff0c;想快速翻译为中文显示&#xff0c;可以借助浏览器的插件来实现。如何安装下面演示谷歌浏览器&#xff0c;如何安装这个插件&#xff1a;打开谷歌应用商店后&#xff08;打不开的话&#xff0c;需要魔法&#xff09;&#xff0c;搜索“沉浸式翻译”…

作者头像 李华
网站建设 2026/6/9 8:58:54

基于springboot + vue医院管理系统

医院管理 目录 基于springboot vue医院管理系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 基于springboot vue医院管理系统 一、前言 博主介绍&#xff1a;✌️大…

作者头像 李华
网站建设 2026/6/9 9:53:20

LangFlow导入已有LangChain代码的兼容性分析

LangFlow 导入已有 LangChain 代码的兼容性分析 在当前 AI 应用快速迭代的背景下&#xff0c;越来越多团队开始构建基于大语言模型&#xff08;LLM&#xff09;的工作流。LangChain 作为主流开发框架&#xff0c;凭借其模块化设计和灵活组合能力&#xff0c;已经成为许多项目的…

作者头像 李华
网站建设 2026/6/9 21:35:28

基于单片机的智能奶瓶(有完整资料)

资料查找方式&#xff1a;特纳斯电子&#xff08;电子校园网&#xff09;&#xff1a;搜索下面编号即可编号&#xff1a;T5332310M设计简介&#xff1a;本设计是基于单片机的智能奶瓶&#xff0c;主要实现以下功能&#xff1a;通过称重模块进行奶瓶称重&#xff0c;进行显示屏显…

作者头像 李华