news 2026/9/22 4:33:31

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/9/21 6:20:05

使用机器学习简化机构沟通,提升可读性与包容性

项目&#xff1a;Simply Simplify Language 利用LLM简化您的机构沟通。摆脱“官僚德语”。 目录 用法项目信息 应用功能成本语言指南一些发现可读性分数如何工作&#xff1f;分数的含义&#xff1f; 项目团队贡献许可证其他免责声明 用法 您可以在本地、云端或在GitHub Codespa…

作者头像 李华
网站建设 2026/9/21 11:58:13

LangFlow降低AI开发门槛:非技术人员也能构建智能应用

LangFlow降低AI开发门槛&#xff1a;非技术人员也能构建智能应用 在大模型时代&#xff0c;企业对AI应用的期待从未如此高涨。然而现实却常常令人沮丧——一个简单的问答机器人原型&#xff0c;往往需要数天甚至数周才能从概念走向可演示版本。产品经理画出流程图后&#xff0c…

作者头像 李华
网站建设 2026/9/22 0:19:03

LangFlow与LangChain协同工作原理深度剖析

LangFlow与LangChain协同工作原理深度剖析 在AI应用开发日益复杂的今天&#xff0c;如何快速构建一个能理解上下文、调用工具、具备记忆能力的智能系统&#xff0c;已成为工程师面临的核心挑战。传统方式下&#xff0c;开发者需要深入掌握LangChain的模块组合逻辑、提示工程技巧…

作者头像 李华
网站建设 2026/9/20 15:51:56

16.2 对齐方法论:FineTune与RAG两大技术路径

16.2 对齐方法论:FineTune与RAG两大技术路径 在上一节中,我们深入探讨了模型微调的必要性,理解了为什么需要让通用大模型理解特定的业务场景。今天,我们将详细对比两种主要的模型对齐技术路径:Fine-tune(微调)和RAG(检索增强生成),帮助大家更好地理解它们的特点、优…

作者头像 李华
网站建设 2026/9/22 2:03:40

16.3 微调技术盘点:产品经理需要了解的核心方法

16.3 微调技术盘点:产品经理需要了解的核心方法 在前两节中,我们探讨了模型微调的必要性和Fine-tune与RAG两种技术路径的对比。今天,我们将深入盘点微调技术的核心方法,帮助产品经理更好地理解和应用这些技术。 微调技术全景图 微调技术发展至今,已经形成了丰富的方法体…

作者头像 李华
网站建设 2026/9/21 13:44:07

汇编语言全接触-41.虚拟设备驱动程序初步

在本教程里&#xff0c;我假定读者对诸如虚8086模式&#xff0c;调页&#xff0c;GDT,LDT,IDT之类的INTEL 80x86保护模式的操作比较熟悉。如果你不了解这些&#xff0c;那你要先在 http://developer.intel.com/design/pentium/manuals/阅读INTEL的文档。 内容&#xff1a;Windo…

作者头像 李华