ACM题目中关于数据的生成以及OJ上Linux和Windows里回车和换行的处理

简介: ACM题目中关于数据的生成以及OJ上Linux和Windows里回车和换行的处理

ACM题目中关于数据的生成以及OJ上Linux和Windows里回车和换行的处理

前言:都是一些浅层的理解,求各位大佬轻喷。

基本的随机数生成

一个好的题目需要有强大的数据来支撑,数据一般由两部分组成,一是边界数据,二是随机数据。对于前者,可能需要手写数据来生成,而后者可以借助rand()函数一次性生成多组随机数据。


因为rand()函数的内部是利用线性同余法实现的,周期较长导致随机性并不强,所以需要在main开始时借助srand()函数设置随机数种子,增强随机性。


代码:

srand(time(0));

对于整数的生成,我们可以借助rand()函数和%来生成固定范围的整数。比如,我想要获得[a,b)内的随机整数,就可以

int tmp=rand()%(b-a)+a;

其实写法有很多种,具体参考:传送门

为了提高生成随机数的随机性,我们可以加一点小优化(maybe有用)

int m=(rand()*rand()+rand())%1000+1;

这时候要注意,如果有题目要求一些数不能重复,比如山理工数据结构实验的选课名单,生成数据的时候就需要用map加一个判重的环节。

map<int,bool>mp;
for(int j=1;j<=cnt;j++){
  int x=(rand()*rand()+rand())%m+1;
  if(mp1[x]){
    j--;
    continue;
  }
  mp1[x]=1;
  cout<<x<<" ";
}

对于随机字母的生成,我们只需要在生成随机数后将随机数转化为字母,代码如下:(全是小写字母的情况)

string name;
int x=(rand()*rand()+rand())%26;
name+=(x+'a');

如果想要不区分大小写的话,可以在增设一个rand()生成固定区间的数,根据区间中点来判断是生成大写还是小写字母。其他方法可以自行寻找~

随机生成多个文件

懂得了以上的随机数生成法则,我们就可以愉快的造数据了。一般OJ的判题规则是在后台有多组数据,每组数据有两种文件,in文件表示该组数据的输入,out文件表示该组数据的输出,后台会运行你的代码并且将in文件的运行结果与out文件对比从而得到AC,WA,PE等多种结果。


生成数据的时候我们要做的就是一次性生成多个对应的in与out文件,上传服务器。


直接就给出学长的代码了,注释已加。


生成数据的题的题面:(好绕口啊) http://icpc.ldu.edu.cn/acm/problem.php?id=2871


大家可以先阅读题目和所给的要求再来结合代码理解(其实主要就是套板子)

#include<bits/stdc++.h>
using namespace std;
#define PI 3.1415926
typedef long long ll;
const int maxn=1e6+7;
const ll mod=1e16;
map<string,bool>mp;///判断名字是否有重复 
map<int,bool>mp1;///判断选课的序号是否有重复 
int main() {
  srand(time(0));//随机数种子 
  for(int qi=1; qi<=15; qi++) {///想生成数据的组数 
  ///以下是修改生成文件的名字 
    char str[120]= {"2871"};//可增加名字,最好为英文,中文容易乱码 
    int len=strlen(str);
    int temp=qi;
    char save[50000];
    int q=0;
    while(temp) {
      save[q++]=(char)((temp%10)+'0');
      temp/=10;
    }
    for(int i=q-1; i>=0; i--)
      str[len++]=save[i];
    str[len]='\0';
    strcat(str,".in");
    freopen(str,"w",stdout);
//------------------------------------------------------------------------------------------------ 
    ///in start
    //(替换为想生成的) 
    //以下是生成in文件的数据,生成数据后输出,因为前面加了文件操作所以会输出到文件里 
    /// int m=(rand()*rand()+rand())%1000+1;
    int n=(rand()*rand()+rand())%350+1,m=(rand()*rand()+rand())%100+1;//生成学生总数和课程数量 
    mp.clear();//清空学生名字的map 
    cout<<n<<" "<<m<<endl;//将学生总数和课程数量输出到文件 
    for(int i=1;i<=n;i++){///生成每一个学生对应的信息 
      mp1.clear();///清空每个学生的选课列表 
      ///生成名字 
      string name;
      int namelen=(rand()*rand()+rand())%6+2;///名字中字母的长度,为了不超长度所以设的小了一点,个人习惯 
      for(int j=0;j<namelen;j++){
        int x=(rand()*rand()+rand())%26; 
        name+=(x+'a');//可以优化为生成大写或小写字母 
      }
      for(int j=0;j<2;j++){//生成名字里的学号 
        int x=(rand()*rand()+rand())%10;
        name+=(x+'0');//转成字符串 
      }
      ///去重名字 
      while(mp[name]){
        name="";
        namelen=(rand()*rand()+rand())%6+2;
        for(int j=0;j<namelen;j++){
          int x=(rand()*rand()+rand())%26;
          name+=(x+'a');
        }
        for(int j=0;j<2;j++){
          int x=(rand()*rand()+rand())%10;
          name+=(x+'0');
        }
      }
      mp[name]=1;//标记名字 
      cout<<name<<" ";//将名字输出到文件里 
      int cnt=(rand()*rand()+rand())%m+1; ///生成该学生的选课数量
      cout<<cnt<<" ";//将该学生的选课数量输出到文件里 
      for(int j=1;j<=cnt;j++){ 
        int x=(rand()*rand()+rand())%m+1;//生成该学生选课的序号 
        if(mp1[x]){//判断之前是否已经出现过,如果出现则该序号不算数 
          j--;
          continue;
        }
        mp1[x]=1;//标记 
        cout<<x<<" ";//将选课序号输出到文件 
      }
      puts("");//输出回车 
    }
//------------------------------------------------------------------------------------------------ 
    ///in end
    //以下为文件读写操作 
    fclose(stdout);
    len=strlen(str);
    str[len-2]='\0';
    strcat(str,"out");
    freopen(str,"w",stdout);
    ///out start
    ///可以加标程什么的 
        ///out end
    fclose(stdout);
  }
  return 0;
}

以上是in文件的数据的生成,对于out文件的数据生成,可以在上述代码里的标程部分添加对应的标程,也可以在数据所在的文件夹里新建cpp文件并将标程放入,在main开头加入:

freopen("1.in","r",stdin);
freopen("1.out","w",stdout);

表示从文件1.in里读取并且输出到1.out文件里。


两种方法各有利弊,看喜好选择啦就。


到这里基本的数据生成已经结束了,大家可以自己出完整的题目啦!


接下来说一下我鼓捣的一下午的事情。


对于有些字符或字符串的题目,可能有时候玄学的标程都会不过,这是因为大部分OJ是Linux系统,而生成数据的时候用的Windows系统,而 windows中的换行符是\r\n, linux/unix下的换行符是\n。 具体的详细的解释可以看博客。


我们要做的就是将Windows的换行符转化为Linux格式的。


这个问题大体可以分为三步,大前提是你要有Linux系统,可以装一个VMware虚拟机,具体的安装教程就不说了(实际上是我不会)


1.将想要更改格式的文件导入虚拟机


2.在虚拟机内完成格式的转化


3.将更改完后的文件导出虚拟机


对于1.3步,可以借助VMware的VMware Tools完成,也可以直接在虚拟机里登入服务器,在虚拟机里进行格式的转化后再将文件上传至服务器。


关键是第二步,有很多方法,这里介绍一种比较好用的,其他方法可参考网上博客


将想要转化的文件所在的文件夹在终端中打开,输入 dos2unix ,后面加文件名,可以是多个。我的虚拟机把语言换了,默认是英文的。

[root@localhost-live 2860]# dos2unix 1.in 2.in 3.in 4.in 5.in 6.in 7.in 8.in 9.in 10.in 11.in 12.in 13.in 14.in 15.in 16.in 17.in 18.in 19.in 20.in
dos2unix: 正在转换文件 1.in 为Unix格式...
dos2unix: 正在转换文件 2.in 为Unix格式...
dos2unix: 正在转换文件 3.in 为Unix格式...
dos2unix: 正在转换文件 4.in 为Unix格式...
dos2unix: 正在转换文件 5.in 为Unix格式...
dos2unix: 正在转换文件 6.in 为Unix格式...
dos2unix: 正在转换文件 7.in 为Unix格式...
dos2unix: 正在转换文件 8.in 为Unix格式...
dos2unix: 正在转换文件 9.in 为Unix格式...
dos2unix: 正在转换文件 10.in 为Unix格式...
dos2unix: 正在转换文件 11.in 为Unix格式...
dos2unix: 正在转换文件 12.in 为Unix格式...
dos2unix: 正在转换文件 13.in 为Unix格式...
dos2unix: 正在转换文件 14.in 为Unix格式...
dos2unix: 正在转换文件 15.in 为Unix格式...
dos2unix: 正在转换文件 16.in 为Unix格式...
dos2unix: 正在转换文件 17.in 为Unix格式...
dos2unix: 正在转换文件 18.in 为Unix格式...
dos2unix: 正在转换文件 19.in 为Unix格式...
dos2unix: 正在转换文件 20.in 为Unix格式...

然后再说说如何将“下载”这个文件夹在终端打开。因为终端只能输入英文字符(maybe),我们右击就会出现该选项。

20200401134307494.png

这个问题还是很烦人的0.0.

结束。




目录
相关文章
|
13天前
|
安全 网络协议 Linux
telnet在windows和linux上的使用方法
Telnet是一个简单且强大的网络工具,广泛用于远程管理和网络诊断。尽管存在安全风险,但在受控环境中,Telnet仍然是一个非常有用的工具。通过本文的介绍,您应该能够在Windows和Linux系统上安装并使用Telnet进行各种网络操作。
75 18
|
1月前
|
安全 Ubuntu Linux
Metasploit Pro 4.22.6-2024111901 (Linux, Windows) - 专业渗透测试框架
Metasploit Pro 4.22.6-2024111901 (Linux, Windows) - 专业渗透测试框架
46 9
Metasploit Pro 4.22.6-2024111901 (Linux, Windows) - 专业渗透测试框架
|
16天前
|
Ubuntu 网络协议 Linux
快速部署WSL(Windows Subsystem for Linux)
WSL提供了一种轻量级的方法,使开发者能够在Windows上无缝运行Linux环境。通过本文介绍的步骤,可以快速安装、配置和使用WSL,以满足开发和测试的需求。
65 8
|
3月前
|
Ubuntu 安全 Linux
|
1月前
|
自然语言处理 安全 Java
Nexpose 7.0.1 for Linux & Windows - 漏洞扫描
Nexpose 7.0.1 for Linux & Windows - 漏洞扫描
42 6
|
1月前
|
关系型数据库 MySQL Linux
MySQL数据库下载安装教程(Windows&Linux)
本文档详细介绍了MySQL的安装步骤,包括安装前的准备工作、下载安装包、Windows和Linux系统下的具体安装流程,以及如何配置MySQL服务、设置环境变量、启动服务和连接数据库等关键操作。
|
2月前
|
NoSQL Linux PHP
如何在不同操作系统上安装 Redis 服务器,包括 Linux 和 Windows 的具体步骤
本文介绍了如何在不同操作系统上安装 Redis 服务器,包括 Linux 和 Windows 的具体步骤。接着,对比了两种常用的 PHP Redis 客户端扩展:PhpRedis 和 Predis,详细说明了它们的安装方法及优缺点。最后,提供了使用 PhpRedis 和 Predis 在 PHP 中连接 Redis 服务器及进行字符串、列表、集合和哈希等数据类型的基本操作示例。
84 4
|
2月前
|
数据库 数据安全/隐私保护 Windows
Windows远程桌面出现CredSSP加密数据修正问题解决方案
【10月更文挑战第30天】本文介绍了两种解决Windows系统凭据分配问题的方法。方案一是通过组策略编辑器(gpedit.msc)启用“加密数据库修正”并将其保护级别设为“易受攻击”。方案二是通过注册表编辑器(regedit)在指定路径下创建或修改名为“AllowEncryptionOracle”的DWORD值,并将其数值设为2。
1044 3
|
1月前
|
存储 缓存 安全
硬盘数据恢复:恢复硬盘数据的9个实用方法(Windows版)
无论是工作文档、家庭照片,还是其他珍贵的数字资产,数据丢失总是一件让人头疼的事情。然而,当硬盘发生问题时,不必过于慌张——只要正确应对,许多数据都可以被成功恢复。本文将从常见数据丢失原因到具体恢复方法,为您提供全面的硬盘数据恢复指导。
|
3月前
|
弹性计算 Linux 数据库
阿里云国际版如何迁移Linux云服务器系统盘中的数据
阿里云国际版如何迁移Linux云服务器系统盘中的数据