Python解题 - CSDN周赛第14期 - 单词编码

news2024/11/19 19:37:16

本期其实没啥好写的,都是数学题,和算法关系不大,唯手熟尔。而且又出现了同一天的每日一练中包含了赛题,这算不算官方泄题呢?看来下次在竞赛之前先做完每日一练大有益处呢。


第一题:字符串全排列

对K个不同字符的全排列组成的数组,面试官从中随机拿走了一个,剩下的数组作为输入, 请帮忙找出这个被拿走的字符串?

比如[“ABC”, “ACB”, “BAC”, “CAB”, “CBA”] 返回 “BCA”

第一行输入整数nn=K!-1),下面n行,每行输入一组剩下的字符串组合。

示例1
输入

5

ABC

ACB

BAC

CAB

CBA

输出BCA

分析

一般来讲第一题都是简单题,所以本题虽然使用全排列查找的算法复杂度是O(n!),但因为数据范围不大,依然可以pass。于是只要穷举出输入字母的所有组合,然后找出少了哪一组,就能得到答案。Python可以直接使用内置的排列组合函数permutations,速度会快上不少。

本题n可以等于0,也就是说K=1,一个字母的组合,那自然是什么都不缺,所以特判,输出一个空字符串既可。

参考代码1

n = int(input())
vector = [input().strip() for _ in range(n)]
if n == 0:
    print("")
else:
    from itertools import permutations
    res = set()
    for i in permutations(vector[0]):
        res.add("".join(i))
    res.difference_update(set(vector))
    print(res.pop())

优化

然鹅,虽然通过了,我们不应该就此满足。仔细观察一下,就能很快找出本题的“窍门”:

如果K个字母的组合没有缺失(总共有K!个组合),那么这些组合从左到右的每个位置上,每个字母都出现了K-1次。比如ABC三个字母的全排列组合ABC,ACB,BAC,BCA,CAB,CBA,第一位出现的是AABBCC,第二位出现的是BCACAB,第三位出现的是CBCABA每个位置的每个字母都出现了两次。于是,如果缺少一组的话,那么只要检查所有组合每位上的字母,出现次数最少的就是答案。这里需要加一个特判,当只有两个字母的时候(n=1),由于只有两种组合,所以只要翻转过来输出字符串即可。

参考代码2

n = int(input())
vector = [input().strip() for _ in range(n)]
if n == 0:
    print("")
elif n == 1:
    print(vector[0][::-1])
else:
    result = ""
    for i in zip(*vector):
        result += min(i, key=i.count) # 找出出现次数最少的字母
    print(result)

第二题:小Q新式棋盘

已知棋盘大小为n*n。每个位置都有自己的权值q。该棋盘中有多少对行权值和小于列权值和?

示例1示例2
输入

3

1 2 3

1 2 3

1 2 3

3

4 5 6

2 3 4

3 2 1

输出35

分析

本题只记得第一个示例,但原理很简单,就是分别计算每行、每列的数字之和,然后比较有多少行的数字之和,小于列的数字之和。作为第二题,数据范围自然也不大,所以O(n^2)嵌套循环的暴力穷举算法就能pass。

参考代码1

n = int(input())
vector = [list(map(int, input().split())) for _ in range(n)]
row = [sum(i) for i in vector]
col = list(map(sum, zip(*vector)))
result = 0
for i in range(n):
    for j in range(n):
        if row[i] < col[j]:
            result += 1
print(result)

优化

同样,我们不能就此满足,本题其实还有更快的算法。先对行权值和列权值进行排序,然后从小到大依次比较,找到行权值比列权值小的位置,然后累加剩下的列权值个数即可。

拿示例二举例,我们计算行权值得到列表[15, 9, 6],排序得到[6, 9, 15],计算列权值得到列表[9, 10, 11],比较两个列表的第一个数字,6小于9,所以累加列权值列表9所在位置(包括9)往后的所有数字的个数3(因为9在第一位,所以如果小于第一个9,那么就代表着所有比它后面所有的数都小),然后再比较行权值列表的第二个数字9,因为不小于列权值列表的第一个数字9,所以比较第二个数字10,由于9小于10,所以累加10后面的数字之和2(包括10自己),答案是5。

如果不算计算行、列权值之和的时间复杂度的话,sort排序的时间复杂度是O(nlogn),比较两个等长列表的时间复杂度是O(n)(其实是2*n,但是惯例舍去系数),所以整体的时间复杂度是O(nlogn)(只保留最高位)。

参考代码2

n = int(input())
vector = [list(map(int, input().split())) for _ in range(n)]
row = sorted(sum(i) for i in vector)
col = sorted(map(sum, zip(*vector)))
i = j = 0
result = 0
while i < n and j < n:
    while j < n and row[i] >= col[j]:
        j += 1
    result += n-j
    if j == n: break # 所有行权值都比列权值大,就没必要继续比下去了
    i += 1
print(result)

第三题:因数-数字游戏

小Q的柠檬汁做完了,掏出了自己的数字卡牌,想要和别人做数字游戏,可是她又不想要输掉游戏。她制定好规则,每次每个人只能把这个牌换成它的因子的某个牌,但是这个因子不能是1或者整数本身。现在给出整数n,两个人开始做游戏,谁无法再给出因子牌则该人胜利。如果该整数无因子牌直接视为先手胜利。请判断先手在最优策略状态下能否必胜,如果能则输出1,不能则输出2。

示例

示例1示例2
输入

6

30

输出21

分析

本题出现在了同一天的每日一练中。。。官方泄题嫌疑。

描述看着十分复杂,无牌可出竟然算胜利,以至于计算的过程中老是绕不过来弯。。。其实这道题非常简单。题目已经说了“这个因子不能是1或者整数本身”,这不摆明就是质数(素数)嘛。所以把题意换个说法就是,剩下一个质数(素数)给对手,对方就获胜了。。。(还是很别扭)。结合输出条件(必胜输出1,反之输出2),可以得出以下条件:

  1. 如果该数是质数(素数),小Q胜,输出1(起手无牌可出)
  2. 如果该数有2个质因数,小Q输,输出2(因为小Q只能打出一个质因数,剩下另一个质数给对方)
  3. 如果该数有3个或以上的质因数,小Q胜,输出1(因为小Q可以打出任意两个质因数的乘积替换该数,把上面第二种情况留给对手)

所以,就是简单的判断分支结构。顺便提一句小技巧,计算某数是否是质数(素数)的时候,只要依次试除到该数的平方根即可。

参考代码

n = int(input())
if n < 4: # 如果该数是1、2、3就不用比了,无牌可出
    print(1)
else:
    for i in range(2, int(n**0.5)+1):
        if n%i == 0:
            p = []
            while n > 1:
                while n%i == 0:
                    n //= i
                    p.append(i)
                if len(p) > 2: # 如果有3个以上的质因数,先手胜
                    print(1)
                    break
                i += 1
            else:
                print(2) # 只有2个质因数,比如6,后手胜
            break
    else:
        print(1) # 该数是质数,起手胜

第四题:编码

编码工作常被运用于密文或压缩传输。这里我们用一种最简单的编码方式进行编码:把一些有规律的单词编成数字。字母表中共有26个字母{a,b,…,z},这些特殊的单词长度不超过6且字母按升序排列。把所有这样的长度相同的单词放在 一起,按字典顺序排列(a...z,ab...az,bc...bz....)一个单词的编码就对应着它在整个序列中的位置。你的任务就是对于所给的单词,求出它的编码,如果没有则输出0。

示例:

示例1示例2
输入

ab

glq

输出271882

分析

本题稍微有点烧脑,但难度并不高,只是比较麻烦。因为“单词长度不超过6”,所以即使穷举,列出所有单词,相信也能过(最后一个单词uvwxyz的编码是313911,所以编码范围就是1到313911)。而本题可以编码的单词字母不允许重复,也必须是按照字母升序排序,所以加个特判,如果输入单词有重复字母,或者不是升序排列,则输出0(就不需要穷举才能证明找不到了)。

但是问哥喜欢找规律,所以这题不满足于穷举(这题明摆着是计算题啊),于是在草稿纸上画出下图(省略右边e到z的列):

所有单词的排列顺序应该如上图所示,不难发现,每个表格中的单词数量都等于其上一行右边一列算起的个数之和。比如第二行第一列a开头的所有两位单词的个数,就等于第一行第二列字母b及后面字母的个数,也就是25。而第三行第一列a开头的所有三位单词个数,等于第二行bc开始的单词个数,加上cd开始的单词个数,加上de开始的单词个数。。。加上yz开始的单词个数。第四行同理。。。

所以,如果本题算做动态规划的话,把上面二维表的每个格子视作某个字母(列)开始的n位单词(行)的个数,可以得到方程如下:

dp[i][j] = sum(dp[i-1][j+1:])

只有第一行,也就是一位字母的那一行,需要全部设置为1,这样就可以通过上面这个公式得到n位单词的一张个数表,而我们要计算单词的排序(编码),只要查表计算就能完成。

计算方法是:从左向右依次取出字母,通过查表找到以该字母开始的n位单词的个数,然后加上所有在它之前的同样长度的单词个数,然后重复此过程,直到最后一个字母。如果设每一位字母在字母表中的位置(顺序)为a[n],则可得公式如下(公式表达不一定准确,以描述为准 :P):

\sum_{i=0}^{n}sum(dp[n-i-1][:a[i]])

此公式的数学证明比较麻烦,这里就略过了(其实也比较简单,就是统计某个字母开始的第一个单词前面出现了多少单词),但即便不用证明,单纯的观察就可以得到上述规律。

拿示例二的单词glq为例,我们根据前面的制表公式可以得到下面这张表:

然后我们依次查找第一位字母g所在的列,累加它所在行它之前的所有数字(包括它自己),也就是图中从300加到171,然后再取第二位字母l,累加它所在行之前的数字(从25加到14),最后再取第三位字母q,累加它之前的所有数字(17个1),最后得到的结果就是答案:1882。

参考代码

word = input().strip()
n = len(word)
if "".join(sorted(list(word))) != word or len(set(word)) != n:
    print(0)
else:
    dp = [[0]*26 for _ in range(n)]
    for i in range(26):
        dp[0][i] = 1
    for i in range(1, n):
        for j in range(25):
            dp[i][j] = sum(dp[i-1][j+1:])
    result = 0
    for i in range(n):
        a = ord(word[n-i-1])-ord("a")+1
        result += sum(dp[i][:a])
    print(result)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/82081.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

算法leetcode|21. 合并两个有序链表(rust重拳出击)

文章目录21. 合并两个有序链表&#xff1a;样例 1&#xff1a;样例 2&#xff1a;样例 3&#xff1a;提示&#xff1a;原题传送门&#xff1a;分析&#xff1a;题解&#xff1a;rustgoccpythonjava21. 合并两个有序链表&#xff1a; 将两个升序链表合并为一个新的 升序 链表并…

一款基于SpringBoot+layui 开源的固定设备资产管理系统源码 源码免费分享

淘源码&#xff1a;国内专业的免费源码下载平台 分享一款开源的固定设备资产管理系统源码&#xff0c;系统可对常用资产设备进行信息化管理&#xff0c;包含自定义支持各类设备、自带导入导出、维护工作统计、采购管理、文档管理、合同管理等功能&#xff0c;包含对资产的登记、…

如何优雅的设计和使用缓存?

背景 在之前的文章中你应该知道的缓存进化史介绍了爱奇艺的缓存架构和缓存的进化历史。俗话说得好&#xff0c;工欲善其事&#xff0c;必先利其器&#xff0c;有了好的工具肯定得知道如何用好这些工具&#xff0c;本篇将介绍如何利用好缓存。 1.确认是否需要缓存 在使用缓存…

CentOS7 修改ip、MAC、UUID

对于复制的虚拟机&#xff0c;在开机时&#xff0c;VMware自动为其分配了相同的Mac地址以及IP地址(除IP地址是dhcp自动获取外) UUID&#xff08;Universally Unique Identifier&#xff09;是系统层面的全局唯一标识符号&#xff0c;Mac地址以及IP地址是网络层面的标识号 两台不…

dtb如何转换到platform_device

分2步&#xff0c;第一步是首先转换为device_node&#xff0c;第二步device_node转换为platform_device。 第一步 /*** unflatten_device_tree - create tree of device_nodes from flat blob** unflattens the device-tree passed by the firmware, creating the* tree of st…

mysql常用索引

1.普通索引 navicat中为NORMAL 语句为 ADD INDEX //采用普通索引的方式可以大大提高数据库的工作效率 2.唯一索引 navicat中为NORMAL 语句为 ADD UNIQUE INDEX //采用唯一索引的方式可以大大提高数据库的工作效率、并且数据无重复 3.主键索引 navicat中为主键 语句为 AD…

ALSA系统简析

一 音频架构 如图所示 是 嵌入式系统的音频连接 音频编解码器将数字音频信号 转换成 扬声器播放所需要的模拟声音信号。而通过麦克风时&#xff0c;则执行相反的过程。 数字音频信号通过 PCM技术对模拟信号以某个比特率采样得到的&#xff0c;编解码器的任务就是以支持的PCM…

非零基础自学计算机操作系统 第1章 操作系统概述 1.4 操作系统的分类 1.4.1 多道批处理操作系统 1.4.2 分时操作系统

非零基础自学计算机操作系统 文章目录非零基础自学计算机操作系统第1章 操作系统概述1.4 操作系统的分类1.4.1 多道批处理操作系统1.4.2 分时操作系统第1章 操作系统概述 1.4 操作系统的分类 按照操作系统的功能可将其分为以下几类&#xff1a;多道批处理操作系统、分时操作系…

力扣(LeetCode)143. 重排链表(C++)

模拟 五步做完 : ①遍历链表&#xff0c;得到链表长度 ②找到中间结点 ③反转链表后半段的结点指向 ④重排链表 ⑤尾结点的指向置空 初始链表 L0→L1→…→Ln−1→LnL0 → L1 → … → Ln - 1 → LnL0→L1→…→Ln−1→Ln 重排链表 L0→Ln→L1→Ln−1→L2→Ln−2→…L0 → Ln…

MongoDB数据库 —— 图形化工具

在前面通过使用MongoDB在命令窗口操作数据库&#xff0c;而MySQL数据库也同样可以在命令窗口使用sql语句操作数据库&#xff0c;在安装数据库的时候提到可以安装这个图形化工具的&#xff0c;为了节省安装时间和卡顿选择后续安装MongoDB图形化工具&#xff0c;在MySQL数据中同样…

[附源码]JAVA毕业设计疫情防控期间人员档案追演示录像上(系统+LW)

[附源码]JAVA毕业设计疫情防控期间人员档案追演示录像上&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#x…

Spring Cloud Zuul网关的介绍及使用

Zuul 是 Netflix OSS 中的一员&#xff0c;是一个基于 JVM 路由和服务端的负载均衡器。提供路由、监控、弹性、安全等方面的服务框架。Zuul 能够与 Eureka、Ribbon、Hystrix 等组件配合使用。 Zuul 的核心是过滤器&#xff0c;通过这些过滤器我们可以扩展出很多功能&#xff0…

猿如意中的【Linux命令查询】工具详情介绍

一、工具名称 Linux命令查询 二、下载安装渠道 Linux命令查询通过CSDN官方开发的【猿如意】客户端进行下载安装。 2.1 什么是猿如意&#xff1f; 猿如意是一款面向开发者的辅助开发工具箱&#xff0c;包含了效率工具、开发工具下载&#xff0c;教程文档&#xff0c;代码片段…

R语言动态可视化:制作历史全球平均温度的累积动态折线图动画gif视频图

在某些情况下&#xff0c;你可能希望通过在每帧中添加数据并保留先前添加的数据来进行动画处理。最近我们被客户要求撰写关于动态可视化的研究报告&#xff0c;包括一些图形和统计输出。 现在&#xff0c;我们将通过制作点线图的动画来探索。 以下是制作图表静态版本的代码&a…

如何打造一个高效可用的组织知识库

作者 | 唐三 在管理改进活动中&#xff0c;衡量一个企业管理改进成功与否的一个重要指标就是组织知识库的构建和使用。 组织知识库是一个学习型组织在项目操作过程中所积累的无形资产&#xff0c;同时组织过程资产的累积程度是衡量一个项目组织管理体系成熟度的重要指标&#…

阿里云ECS安装VirtualBox

文章目录virtualbox repovirtualbox repo适配阿里云的OS修改virtualbox repo成功下载安装报错安装 libvpxvirtualbox repo [virtualbox] nameOracle Linux / RHEL / CentOS-$releasever / $basearch - VirtualBox baseurlhttp://download.virtualbox.org/virtualbox/rpm/rhel/…

C#开发——Winform中ToolTip闪烁的解决方案

1、背景 首先要知道在何种情况下需要用tooltip控件&#xff0c;使用场景应该是&#xff1a;鼠标移入某个控件区域&#xff0c;显示tooltip的提示&#xff1b;移出后隐藏该提示。 采用的比较多的方式是&#xff0c;对该控件的MouseMove和MouseLeave事件进行处理。 至于为什么不是…

【产品人卫朋】华为销售体系 | 销售管理:LTC流程体系详解

LTC 是华为的三大主流程之一&#xff0c;从线索发现开始&#xff0c;直至收回现金&#xff0c;从而实现端到端地拉通。 三大主流程分别是&#xff1a; 其他流程可以参考之前文章&#xff1a; 华为IPD流程 华为ITR流程 继续今天的内容&#xff0c;在不同的流程环节卷入不同的…

[1.2.0新功能系列:一] Apache Doris 1.2.0 版本 Light Schema Change

在 1.2.0 新版本中&#xff0c;对数据表的加减列操作&#xff0c;不再需要同步更改数据文件&#xff0c;仅需在 FE 中更新元数据即可&#xff0c;从而实现毫秒级的 Schema Change 操作&#xff0c;且存在导入任务时效率的提升更为显著。与此同时&#xff0c;使得 Apache Doris …

干货 | Dubbo 接口测试原理及多种方法实践总结

1、什么是 Dubbo&#xff1f; Dubbo 最开始是应用于淘宝网&#xff0c;由阿里巴巴开源的一款优秀的高性能服务框架&#xff0c;由 Java 开发&#xff0c;后来贡献给了 Apache 开源基金会组织。 下面以官网的一个说明来了解一下架构的演变过程&#xff0c;从而了解 Dubbo 的诞…