对拍程序

前言

有时做题偶然会想到一个好的方法,但是不能保证正确性
于是,可以写一个正确的程序与不确定的程序进行对拍,判定方法的正误

正题

题目描述

求逆序对,其中 \(n\le 10^5\)
输入文件名 data.in
输出文件名 data.out

标程(exe)

首先,要过 \(10^5\) 的数据点,\(n^2\) 暴力是不行滴
显然,归并就能解
于是,写了这一段
文件名是 std.cpp

#include<cstdio>
#define maxn 100005
using namespace std;
typedef long long ll;
int n,a[maxn],c[maxn];
ll ans=0;
void msort(int L,int R){
    int i,j,mid=L+R>>1;
    if (L>=R) return;
    msort(L,mid),msort(mid+1,R);
    for (int k=L;k<=R;k++) c[k]=a[k];
    i=L,j=mid+1;
    for (int k=L;k<=R;k++){
        if (i<=mid && (j>R || c[i]<=c[j])) a[k]=c[i++];
        else a[k]=c[j++],ans+=mid-i+1;
    }
}
int main(){
    freopen("data.in","r",stdin);
    freopen("data.out","w",stdout);
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",a+i);
    msort(1,n);
    printf("%lld\n",ans);
    return 0;
}

暴力(exe)

编译,测样例,似乎没有问题
但是,为了保险,你不知道有没有问题时就对拍
于是,又写了一段
文件名是 sb.cpp

#include<cstdio>
using namespace std;
typedef long long ll;
int n,a[100001];
ll ans;
int main(){
    freopen("data.in","r",stdin);
    freopen("data0.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",a+i);
    for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j++)
            if(a[j]<a[i]) ans++;
    printf("%lld\n",ans);
    return 0;
}

数据生成器(exe)

接下来是数据生成器,本人太菜,不会 python
听说 python 还是挺好用的

首先,明确一点 c++rand() 返回的是 \([0,2^{15}-1]\) 的正整数,而我们需要 \([0,2^{31}-1]\)
因此需要一个函数,生成 \([0,2^{31}-1]\) ,自己理解一下

inline int brand(){ return (rand()<<16)+(rand()<<1)+(rand()&1); }

开头不要忘了随机化种子,不然每组随机数都是一样的

这是使用 WINDOWS.H 里的 GetTickCount() 函数的,该函数返回从操作系统启动所经过的毫秒数,它的返回值是 DWORD,所以每次的种子都不一样,而且比 ctime 中的 time(0) 变化速度快,是每毫秒改变一次。

文件名是 make_data.cpp

整个数据生成的代码如下,在 data.in 中输出一个 \(n\)\(n\) 个数

#include <cstdio>
#include <cstdlib>
#include <WINDOWS.h>

#define MAXN 1000
#define MAXX 1000000000

inline int brand(){ return (rand()<<16)+(rand()<<1)+(rand()&1); }

int n;

int main(){
    freopen("data.in","w",stdout);
    srand(GetTickCount());
    n=brand()%MAXN+1;
    printf("%d\n",n);
    for (int i=1;i<=n;i++){
        int x=brand()%MAXX+1;
        printf("%d\n",x);
    }
    return 0;
}

然而有的电脑不支持 WINDOWS.H,就只好使用 ctime,但是在同一秒内的种子是一样的

#include <ctime>
#include <cstdio>
#include <cstdlib>

#define MAXN 1000
#define MAXX 1000000000

inline int brand(){ return (rand()<<16)+(rand()<<1)+(rand()&1); }

int n;

int main(){
    freopen("data.in","w",stdout);
    srand(time(0));
    n=brand()%MAXN+1;
    printf("%d\n",n);
    for (int i=1;i<=n;i++){
        int x=brand()%MAXX+1;
        printf("%d\n",x);
    }
    return 0;
}

个人较喜欢第一种

比较程序(bat)

使用批处理中的 fc 函数进行比较
文件夹中需要有 make_data.exestd.exesb.exe
自带输入输出:

@echo off
:loop
make_data.exe
std.exe
sb.exe
fc data.out data0.out
if errorlevel 1 pause
goto loop

标准输入输出:

@echo off
:loop
make_data.exe
std.exe < data.in > data.out
sb.exe < data.in > data0.out
fc data.out data0.out
if errorlevel 1 pause
goto loop

后记

对拍在比赛时特别有用,当写完题目有时间时,不妨对拍一下哦

posted @ 2018-06-01 16:44 xay5421 阅读(...) 评论(...) 编辑 收藏