Python在竞赛中的应用-测试数据的构造与对拍 --算法专题精解(31)
本系列文章将于2021年整理出版,书名《算法竞赛专题解析》。
前驱教材:《算法竞赛入门到进阶》 清华大学出版社
网购:京东 当当 作者签名书
如有建议,请加QQ 群:567554289,或联系作者QQ:15512356
文章目录
- C.1 计算大数
- C.2 构造随机数和随机字符串
- C.3 数组去重
- C.4 构造测试数据和对拍
很多人认为Python是最受欢迎的编程语言,它编码简洁,有强大的库。
Python早已应用在算法竞赛中,能节省大量比赛时间。
大学的某些算法竞赛(ICPC)已经支持用Python语言提交代码。即使比赛不支持用Python提交代码,而Linux系统一般是预装Python的,可以用Python做辅助工作。
Python的优点有编码简便、处理大数非常简单、构造测试数据比C++更简单等。Python的主要问题是执行时间慢,比C++、java慢得多,竞赛队员可能不会直接用Python交题。不过,Python可以作为工具使用,常用的是构造数据、写对拍代码。一个典型的应用是:如果能用打表法交题,可以先用python打表出数据,然后用c++或直接用Python提交。
读者会发现,用Python做这些事,比用C++容易得多,这在紧张的比赛中是很有用的。
若读者想学习用Python写算法竞赛题的代码,建议到力扣网站(leetcode-cn.com)练习,每个题都有人提交Python题解。
Python的强大,主要是因为它庞大的库。Python有两种版本Python 2、Python 3,两者不兼容。本节基于 Python 3。Python编译环境下载地址:https://www.python.org/downloads/
下面介绍Python在算法竞赛中的应用。
C.1 计算大数
下面的题目是计算大数。
阶乘之和 洛谷 P1009https://www.luogu.com.cn/problem/P1009
题目描述:计算S=1!+2!+3!..+n! (n≤50)
计算结果是一个天文数字,如果用C++编码,需要用高精度,很复杂。而Java和python都能直接处理大数。
用Java编码很简单:
import java.math.*;
import java.util.*;
public class Main {public static void main(String[] args) {Scanner in= new Scanner(System.in);int n = in.nextInt(); BigInteger s = new BigInteger("1");BigInteger ans = new BigInteger("0");for (int i = 1; i <= n; i++) {s = s.multiply(new BigInteger(String.valueOf(i)));ans = ans.add(s);}System.out.println(ans);}
}
用Python编码更简单:
n = int(input())
s = 1
ans = 0
for i in range(1,n+1,1): s *= ians += s
print(ans)
C.2 构造随机数和随机字符串
用Python构造测试数据,比c++简单得多。它能直接产生极大的数字,方便地产生随机字符等。下表列出了一些典型的随机数、随机字符串构造方法1。
(1)导入库
import random
可以写成:
from random import *
此时后面的代码能够简单一点,例如把random.randint
直接写为randint
(2)在指定范围内生成一个很大的随机整数:
print (random.randint(-9999999999999999,9999999999999999))
输出示例:428893995939258
(3)在指定范围内(0到100000)生成一个随机偶数:
print (random.randrange(0, 100001, 2))
输出示例:14908
(4)生成一个0到1之间的随机浮点数:
print (random.random())
输出示例:0.2856636141181378
(5)在指定范围内(1到20)生成一个随机浮点数:
print (random.uniform(1, 20))
输出示例:9.81984258258233
(6)在指定字符中生成一个随机字符:
print (random.choice('abcdefghijklmnopqrst@#$%^&*()'))
输出示例:d
(7)在指定字符中生成指定数量的随机字符:
print (random.sample('zyxwvutsrqponmlkjihgfedcba',5))
输出示例:[‘z’, ‘u’, ‘x’, ‘w’, ‘j’]
(8)导入库
import string
若写成from string import *
,下面的string.ascii_letters
改为ascii_letters
(9)用a-z、A-Z、0-9生成指定数量的随机字符串:
ran_str = ''.join(random.sample(string.ascii_letters + string.digits, 8))
print (ran_str)
输出示例:iCTm6yxN
(10)从多个字符中选取指定数量的字符组成新字符串:
print (''.join(random.sample(['m','l','k','j','i','h','g','d'], 5)))
输出示例:mjlhd
(11)打乱数组的顺序:
items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
random.shuffle(items)
for i in range(0,len(items),1): #逐个打印print (items[i]," ",end='')
输出示例:1 0 8 3 5 7 9 4 6 2
C.3 数组去重
1、整数去重
随机生成的整数,很多是重复的,而一般情况下需要不重复的数据。下面给出两种去重方法。
第1种方法用set(),速度极快。set()的时间复杂度差不多是O(n)的,和生成随机数的时间差不多。set()去重不能保持数据的原顺序。set()去重的原理是hash,所以有时候它返回的结果中部分数据看起来像排过序,但整体上并不是有序的。虽然set()去重后的数据的顺序不是那么随机,但是可以用shuffle()再次把数据打乱,得到排序随机的数组。
第2种方法是暴力去重,非常非常慢,不过它的结果保持了原数据的顺序。
def NonRepeatList1(data): #函数1:set去重,不保持原顺序return list(set(data))
def NonRepeatList2(data): #函数2:暴力去重,保持原顺序return [i for n, i in enumerate(data) if i not in data[:n]]
#下面测试上面2个函数
import random
import time
time0 = time.time()
a = []
for i in range(0,100000,1): #10万个随机数a.append(random.randint(-100000000,100000000)) #随机数取值范围
#print (a) #可以打印数组看看
print ("random time =",time.time()-time0) #统计随机数的生成时间time0 = time.time()
b = NonRepeatList1(a) #去重,不保持原顺序
#print (b) #打印看看顺序
random.shuffle(b) #再次打乱顺序
#print (b) #打印看看是否乱序
print ("set time =",time.time()-time0) #统计set()去重的时间time0 = time.time()
c = NonRepeatList2(a) #去重,保持原顺序
#print (c) #打印看看是否保持原序
print ("enum time =",time.time()-time0) #统计暴力去重的时间
代码中统计了两种方法的执行时间,在作者的电脑上运行,10万个数的时间是:
random time = 0.10671424865722656
set time = 0.06288003921508789
enum time = 99.96579337120056
可见set()是极快的,是暴力去重的1600倍。
再试试1000万个数,生成随机数和去重的时间是:
random time = 10.069396495819092
set time = 10.71152925491333
2、小数去重
如果要生成不同的小数,简单的办法是先用上面的代码生成去重整数数组,然后把每个整数除以10的幂次即可。例如生成2位小数,把每个整数除以100。
d = []
for i in range(0,len(b),1): #b是去重后的整数数组d.append(b[i] / 100)
C.4 构造测试数据和对拍
1、构造测试数据
仍然以Hdu 1425为例。
hdu 1425 sort http://acm.hdu.edu.cn/showproblem.php?pid=1425
给你n个整数,请按从大到小的顺序输出其中前m大的数。
输入:每组测试数据有两行,第一行有两个数n, m(0 < n, m < 1000000),第二行包含n个各不相同,且都处于区间[-500000, 500000]的整数。
输出:对每组测试数据按从大到小的顺序输出前m大的数。
首先构造测试数据。下面的代码生成60多万个不同的无序的随机数。首先产生100万个随机数,然后用set去重,最后用shuffle打乱即可。
#设本代码的文件名是aa.py
import random
a= []
b= []
for i in range(0,1000000,1): #100万个随机数a.append(random.randint(-500000,500000))
b=list(set(a)) #去重#print("lena=",len(a)) #验证a的个数是不是100万个
#print("lenb=",len(b)) #b的个数有60多万个random.shuffle(b) #打乱b
print(len(b),random.randint(1,len(b))) #打印n、m
for i in range(0,len(b),1): #逐个打印print ( b[i],end=' ') #下面的做法是存到一个文件里面,其实不需要
'''
f = open("d:\data.in", "w") #输出到文件里
print(len(b),random.randint(1,len(b)),file=f)
for i in range(0,len(b),1): #逐个打印print ( b[i],end=' ',file=f)
f.close()
'''
2、对拍
下面以Windows环境为例说明构造测试数据和对拍的过程,linux环境类似。
把上面的代码存为文件aa.py,执行下面的命令,输出测试数据到文件data.in
D:\>C:\Users\hp\AppData\Local\Programs\Python\Python39\python aa.py >data.in
作者的python安装在目录C:\Users\hp\AppData\Local\Programs\Python\Python39\
,读者可以按自己的目录操作,或者设置环境变量,就不用输这个目录了。
下面给出Hdu 1425的对拍代码,功能是:先输入n和m,然后输入n个数,排序后,打印出前m大的数。与C++对拍代码相比,Python代码更简单。
#设本代码的文件名是bb.py
n,m = map(int,input().split()) #输入n、m
a=[int(n) for n in input().split()] #输入n个数
a.sort() #排序
for i in range(n-1,n-m,-1): #打印出前m-1大的数print ( a[i],end=' ')
print ( a[n-m]) #打印出第m大的数
把代码存为文件bb.py。Windows环境下,执行以下命令,读输入数据data.in,输出数据到py.out
D:\>C:\Users\hp\AppData\Local\Programs\Python\Python39\python bb.py <data.in >py.out
前一节“测试数据的构造与对拍https://blog.csdn.net/weixin_43914593/article/details/106863166”的c++代码是:
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1000001;
int a[MAXN];
int main(){int n,m;while(~scanf("%d%d", &n, &m)){memset(a, 0, sizeof(a));for(int i=0; i<n; i++){int t;scanf("%d", &t); //此题数据多,如果用很慢的cin输入,肯定TLEa[500000+t]=1; //数字t,登记在500000+t这个位置}for(int i=MAXN; m>0; i--)if(a[i]){if(m>1) printf("%d ", i-500000);else printf("%d\n", i-500000);m--;}}return 0;
}
设代码的文件名是hash,执行代码,读取输入data.in,输出到文件hash.out
D:\>hash <data.in >hash.out
下面比较2个代码的输出是否一样,执行以下命令:
D:\>fc py.out hash.out /n
若文件一样,输出(上面一行中的hash.out
,在下面显示HASH.OUT
,这不是笔误):
正在比较文件 py.out 和 HASH.OUT
FC: 找不到差异
3、把所有过程写成批处理文件2
(1)windows环境
把上述过程写成windows环境的bat批处理。它是一个死循环,在每个循环生成数据并对拍,直到发现错误,出错误的那组输入和输出都留在文件中,可以查看。下面代码中的路径是作者电脑的路径,请读者改为自己电脑的路径。
@echo off
set path=C:\MinGW\bin
g++ -o hash.exe hash.cpp
:loop
set path=C:\Users\hp\AppData\Local\Programs\Python\Python39
python aa.py >data.in
hash.exe <data.in >hash.out
python bb.py <data.in >py.out
set path=C:\Windows\System32
fc py.out hash.out
if errorlevel == 1 pause
goto loop
(2)linux环境
linux的文件比较命令是diff。
[root]#diff -c hash.out sort.out
本文没有在linux环境中试Python,这里给出一个c++的参考,功能类似。
#!bin/bash
while true; dogcc hash.cpp -o hash.exegcc sort.cpp -o sort.exegcc makedata.cpp -o makedata.exe./makedata.exe >data.in./hash.exe <data.in >hash.out./sort.exe <data.in >sort.outif diff hash.out sort.out; thenecho OKelse echo wrongbreakfi
done
参考https://www.cnblogs.com/zqifa/p/python-random-1.html ↩︎
感谢华东理工大学17级队员李震 ↩︎
Python在竞赛中的应用-测试数据的构造与对拍 --算法专题精解(31)相关推荐
- python处理列表中字典_Python 列表、元组、字典及集合操作详解
一.列表 列表是Python中最基本的数据结构,是最常用的Python数据类型,列表的数据项不需要具有相同的类型 列表是一种有序的集合,可以随时添加和删除其中的元素 列表的索引从0开始 1.创建列表 ...
- Python组合列表中多个整数得到最小整数(一个算法的巧妙实现)
'''程序功能: 给定一个含有多个整数的列表,将这些整数任意组合和连接, 返回能得到的最小值. 代码思路: 将这些整数变为相同长度(按最大的进行统一),短的右侧使用个位数补齐 ...
- python竞赛_浅谈Python在信息学竞赛中的运用及Python的基本用法
浅谈Python在信息学竞赛中的运用及Python的基本用法 前言 众所周知,Python是一种非常实用的语言.但是由于其运算时的低效和解释型编译,在信息学竞赛中并不用于完成算法程序.但正如LRJ在& ...
- 信息学奥赛 python 教程_Python在信息学竞赛中的运用及Python的基本用法(详解)
前言 众所周知,Python是一种非常实用的语言.但是由于其运算时的低效和解释型编译,在信息学竞赛中并不用于完成算法程序.但正如LRJ在<算法竞赛入门经典-训练指南>中所说的一样,如果会用 ...
- 竞赛中常用的Python 标准库
对竞赛中常用得标准库进行解析和给出代码模板 目录 1.functools 1.1 cmp_to_key 1.2 lru_cache(记忆化存储,加快递归速度) 2.collections 2.1 ...
- Python,OpenCV中的K均值聚类——K-Means Cluster
Python,OpenCV中的K均值聚类 1. 效果图 2. 原理 2.1 什么是K均值聚类? 2.2 K均值聚类过程 2.3 cv2.kmeans(z, 2, None, criteria, 10, ...
- Python,OpenCV中的K近邻(knn K-Nearest Neighbor)及改进版的K近邻
Python,OpenCV中的K近邻(knn K-Nearest Neighbor)及改进版的K近邻 1. 效果图 2. 源码 参考 这篇博客将介绍将K-最近邻 (KNN K-Nearest Neig ...
- 竞赛专题(四)特征工程-竞赛中的必杀技
点击上方"Datawhale",选择"星标"公众号 第一时间获取价值内容 为了帮助更多竞赛选手入门进阶比赛,通过数据竞赛提升理论实践能力和团队协作能力.Data ...
- 非科班生如何浑水摸鱼在省级大数据竞赛中获奖
以各种竞赛为线索的回忆录/经验贴,没写算法啥的,就是记比赛过程,本科除了看的那几本书,打的那十几场竞赛,寝室那几个人,几位恩师的脸,很多都记不清了. 这次记录的比赛是:2017年安徽省大数据技术与应用 ...
最新文章
- Python的Crypto模块使用:自动输入Shell中的密码
- typora高级设置字体_Mint(Linux)系统设置优化及其常用软件安装笔记
- AndroidManifest.xml配置文件属性详解
- Cognos TM1_10.1.1服务端配置
- php隐藏路径ngnix,thinkphp框架在nginx环境下去掉index.php路径显示
- 基于WF4的新平台-流程模式-(9)表单路由启动传入
- (67)Verilog HDL模块条件例化
- 各种数据库的分页查询
- python install_[Python] Linux下python install
- html5数学公式编辑器,数学公式编辑器的使用技巧
- python逐行写入txt文件_Python中将变量按行写入txt文本中的方法
- 《控制论导论》读书:机构-黑箱
- openwrt web框架luci简介,20行代码写一个前后端交互页面
- 【利用Python进行数据分析】13 - Python建模库介绍
- python语言的注释语句引导符不包括什么_以下选项中,哪一个是Python语言中代码注释使用的符号?________...
- 优雅的使用MacBook(一些小技巧,你不会知道的)
- SEC:马斯克在法官批准和解协议之后再发推特时 并未向公司请示
- 1.4 爬虫-笔趣阁获取小说例子
- 在10亿像素图像中发现预后模式 FINDING PROGNOSTIC PATTERNS IN GIGAPIXEL IMAGES
- Chef学习之三:Chef基础知识 (转贴)