zoukankan      html  css  js  c++  java
  • 随机数据生成与对拍【c++版,良心讲解】

    10.7更新:见最下面

    离NOIP2018没剩多长时间了,我突然发现我连对拍还不会,于是赶紧到网上找资料,找了半天发现了一个特别妙的程序,用c++写的!

     

    不过先讲讲随机数据生成吧。

    很简单,就是写一个程序模拟输入数据,然后利用rand()编写随机数。

    在头文件cstdlib中,有rand(), srand()函数,以及常量RAND_MAX.

    RAND_MAX在windos系统中为 0x7fff = 2^15-1 = 32767;在Unix(可以理解为linux,只不过linux是unix一种,是”类unix“)下为 2^31-1 = 2147483647(都是32位),加上一个正数最高位就为1,就变成了负数,即 -RAND_MAX = RAND_MAX + 1,所以 - rand() / RAND_MAX = rand() / (RAND_MAX + 1)。

    rand()返回一个在0~RAND_MAX之间的整数。

    srand(seed)函数接受一个unsigned int类型的参数seed,以seed为“随机种子”。

    rand()函数基于线性同余递推式(就是某种递推式吧~)生成随机数,“随机种子“相当于这个递推式的初始参数,若不执行srand(),则种子默认为1.

    当种子确定后,生成的随机数列也是固定的,因此这种随机方法是”伪随机“,所以一般要在开始调用srand(),且以当前时间为随机种子。

    怎么写呢?ctime里有一个tim函数,调用time(0)可以返回从1970年1月1日0时0分0秒(Unix纪元)到现在的秒数。然后写这么一句就行了:srand((unsigned)time(0));

     

    接下来才是重点:对拍~~

    对拍是啥我就不多说了,直接讲怎么写。

    首先,得有这么几个程序:

    1.随机数据生成程序random.cpp.

    2.自己的美妙算法程序sol.cpp

    3.暴力程序bf.cpp (bf:brute force 暴力)

    然后我们要写一个脚本,循环执行以下过程:

    1.运行random.exe.

    2.运行sol.exe

    3.运行bf.exe

    4.比对sol.out和bf.out的内容是否一致。

    虽然Windos和类unix分别有bat批处理脚本和bash脚本,然而因为我太懒不想学别的语言,就废了半天功夫找到了一个用c++写的(你这道勤快)。

    还是在cstdlib中,有一个system函数,他接受一个字符串作为参数,然后把这个字符串作为系统命令执行,栗如:system("C:\Users\Administrator\Desktop\random.exe"),执行windos桌面上的random.exe。

    比对的话,windows用fc,类Unix用diff,他们接受两个文件路径,比较二者是否一致,若一致返回0,否则返回非0值。

    下面放出windos的对拍程序,程序都是在桌面上的

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<cctype>
     8 #include<vector>
     9 #include<stack>
    10 #include<queue>
    11 #include<ctime>
    12 using namespace std;
    13 #define enter puts("") 
    14 #define space putchar(' ')
    15 #define Mem(a) memset(a, 0, sizeof(a))
    16 typedef long long ll;
    17 typedef double db;
    18 const int INF = 0x3f3f3f3f;
    19 const int eps = 1e-8;
    20 //const int maxn = ;
    21 inline ll read()
    22 {
    23     ll ans = 0;
    24     char ch = getchar(), last = ' ';
    25     while(!isdigit(ch)) {last = ch; ch = getchar();}
    26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
    27     if(last == '-') ans = -ans;
    28     return ans;
    29 }
    30 inline void write(ll x)
    31 {
    32     if(x < 0) x = -x, putchar('-');
    33     if(x >= 10) write(x / 10);
    34     putchar(x % 10 + '0');
    35 }
    36 
    37 int main()
    38 {
    39     for(int t = 1; t <= 100; ++t)
    40     {
    41         system("C:\Users\Administrator\Desktop\random.exe");
    42         db Beg = clock();            //记录sol.exe的运行时间 
    43         system("C:\Users\Administrator\Desktop\sol.exe");
    44         db End = clock();
    45         system("C:\Users\Administrator\Desktop\bf.exe");
    46         if(system("fc C:\Users\Administrator\Desktop\sol.out C:\Users\Administrator\Desktop\bf.out"))
    47         {
    48             puts("WA"); return 0;
    49         }
    50         else printf("AC, #%d, Time : %.0lfms
    ", t, End - Beg);
    51     }
    52     return 0;
    53 }
    View Code

    类unix上的对拍程序,只需要更改上面的代码system中的路径格式,把fc改成diff,用时单位该为”秒“(windos是毫秒)。

    于是我又写了一个linux下的,奇特的是,双斜杠单斜杠竟然都行,而且时间还是以毫秒为单位……

     1 #include<cstdio>
     2 #include<ctime>
     3 #include<cstdlib>
     4 using namespace std;
     5 typedef double db;
     6 
     7 int main()
     8 {
     9   for(int i = 1; i <= 10000; ++i)
    10     {
    11       system("//home//noilinux//Desktop//random");
    12       db Beg = clock();
    13       system("//home//noilinux//Desktop//sol");
    14       db End = clock();
    15       system("//home//noilinux//Desktop//bf");
    16       if(system("diff //home//noilinux//Desktop//sol.out //home/noilinux//Desktop//bf.out"))
    17       {
    18       puts("WA"); return 0;
    19       }
    20       else printf("AC #%d, Time : %.0lfms
    ", i, End - Beg);
    21     }
    22   return 0;
    23 }
    View Code

     

    这里给一个a + b的对拍程序:

    首先是random.cpp

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<cctype>
     8 #include<vector>
     9 #include<stack>
    10 #include<queue>
    11 #include<ctime>
    12 using namespace std;
    13 #define enter puts("") 
    14 #define space putchar(' ')
    15 #define Mem(a) memset(a, 0, sizeof(a))
    16 typedef long long ll;
    17 typedef double db;
    18 const int INF = 0x3f3f3f3f;
    19 const int eps = 1e-8;
    20 //const int maxn = ;
    21 inline ll read()
    22 {
    23     ll ans = 0;
    24     char ch = getchar(), last = ' ';
    25     while(!isdigit(ch)) {last = ch; ch = getchar();}
    26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
    27     if(last == '-') ans = -ans;
    28     return ans;
    29 }
    30 inline void write(ll x)
    31 {
    32     if(x < 0) x = -x, putchar('-');
    33     if(x >= 10) write(x / 10);
    34     putchar(x % 10 + '0');
    35 }
    36 
    37 int main()
    38 {
    39     freopen("random.in", "w", stdout);
    40     srand((unsigned)time(0));
    41     write(rand() % rand()); space; write(rand() % rand());
    42     return 0;
    43 }
    View Code

    然后是sol.cpp(随便拷的一份LCT的……巨啊)

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<cstring>
      5 using namespace std;
      6 struct node 
      7 {
      8     int data,rev,sum;
      9     node *son[2],*pre;
     10     bool judge();
     11     bool isroot();
     12     void pushdown();
     13     void update();
     14     void setson(node *child,int lr);
     15 }lct[233];
     16 int top,a,b;
     17 node *getnew(int x)
     18 {
     19     node *now=lct+ ++top;
     20     now->data=x;
     21     now->pre=now->son[1]=now->son[0]=lct;
     22     now->sum=0;
     23     now->rev=0;
     24     return now;
     25 }
     26 bool node::judge(){return pre->son[1]==this;}
     27 bool node::isroot()
     28 {
     29     if(pre==lct)return true;
     30     return !(pre->son[1]==this||pre->son[0]==this);
     31 }
     32 void node::pushdown()
     33 {
     34     if(this==lct||!rev)return;
     35     swap(son[0],son[1]);
     36     son[0]->rev^=1;
     37     son[1]->rev^=1;
     38     rev=0;
     39 }
     40 void node::update(){sum=son[1]->sum+son[0]->sum+data;}
     41 void node::setson(node *child,int lr)
     42 {
     43     this->pushdown();
     44     child->pre=this;
     45     son[lr]=child;
     46     this->update();
     47 }
     48 void rotate(node *now)
     49 {
     50     node *father=now->pre,*grandfa=father->pre;
     51     if(!father->isroot()) grandfa->pushdown();
     52     father->pushdown();now->pushdown();
     53     int lr=now->judge();
     54     father->setson(now->son[lr^1],lr);
     55     if(father->isroot()) now->pre=grandfa;
     56     else grandfa->setson(now,father->judge());
     57     now->setson(father,lr^1);
     58     father->update();now->update();
     59     if(grandfa!=lct) grandfa->update();
     60 }
     61 void splay(node *now)
     62 {
     63     if(now->isroot())return;
     64     for(;!now->isroot();rotate(now))
     65     if(!now->pre->isroot())
     66     now->judge()==now->pre->judge()?rotate(now->pre):rotate(now);
     67 }
     68 node *access(node *now)
     69 {
     70     node *last=lct;
     71     for(;now!=lct;last=now,now=now->pre)
     72     {
     73         splay(now);
     74         now->setson(last,1);
     75     }
     76     return last;
     77 }
     78 void changeroot(node *now)
     79 {
     80     access(now)->rev^=1;
     81     splay(now);
     82 }
     83 void connect(node *x,node *y)
     84 {
     85     changeroot(x);
     86     x->pre=y;
     87     access(x);
     88 }
     89 void cut(node *x,node *y)
     90 {
     91     changeroot(x);
     92     access(y);
     93     splay(x);
     94     x->pushdown();
     95     x->son[1]=y->pre=lct;
     96     x->update();
     97 }
     98 int query(node *x,node *y)
     99 {
    100     changeroot(x);
    101     node *now=access(y);
    102     return now->sum;
    103 }
    104 int main()
    105 {
    106     freopen("random.in", "r", stdin);
    107     freopen("sol.out", "w", stdout);
    108     scanf("%d%d",&a,&b);
    109     node *A=getnew(a);
    110     node *B=getnew(b);
    111     //连边 Link
    112         connect(A,B);
    113     //断边 Cut
    114         cut(A,B);
    115     //再连边orz Link again
    116         connect(A,B);
    117     printf("%d
    ",query(A,B)); 
    118     return 0;
    119 }
    View Code

    最后是bf.cpp

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<cctype>
     8 #include<vector>
     9 #include<stack>
    10 #include<queue>
    11 using namespace std;
    12 #define enter puts("") 
    13 #define space putchar(' ')
    14 #define Mem(a) memset(a, 0, sizeof(a))
    15 typedef long long ll;
    16 typedef double db;
    17 const int INF = 0x3f3f3f3f;
    18 const int eps = 1e-8;
    19 //const int maxn = ;
    20 inline ll read()
    21 {
    22     ll ans = 0;
    23     char ch = getchar(), last = ' ';
    24     while(!isdigit(ch)) {last = ch; ch = getchar();}
    25     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
    26     if(last == '-') ans = -ans;
    27     return ans;
    28 }
    29 inline void write(ll x)
    30 {
    31     if(x < 0) x = -x, putchar('-');
    32     if(x >= 10) write(x / 10);
    33     putchar(x % 10 + '0');
    34 }
    35 
    36 int main()
    37 {
    38     freopen("random.in", "r", stdin);
    39     freopen("bf.out", "w", stdout);
    40     int a = read(), b = read();
    41     write(a + b); enter;
    42 }
    View Code

    把三个程序分别运行一下,得到三个exe。然后运行上面的对拍程序就行啦~~

    附一下效果

     如果把bf改成write(a +b + 1)的话:

    这时候出错的数据就是当前的random.in了~~

    ***10月7日更新***

    小云彩(tql)告诉我了一个更简便的写法。

    在调用system的时候,里面可以不用写的那么复杂。如果这些东西在同一目录下,我们只用这么写:

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<ctime>
     4 typedef double db;
     5 using namespace std;
     6 
     7 int main()
     8 {
     9     for(int t = 1; t <= 1000; ++t)
    10     {
    11         system(".\random.exe");
    12         db Beg = clock();
    13         system(".\ac.exe");
    14         db End = clock();
    15         system(".\bf.exe");
    16         if(system("fc .\ac.out .\bf.out"))
    17         {
    18             printf("WA
    "); return 0;
    19         }
    20         else printf("#%d AC %.2lfms
    ", t, End - Beg);
    21     }
    22     return 0;
    23 }
    View Code

    windos下用 .//,linux下是 ~\。

    方便。

    对拍讲完啦~~~祝各位继续AKIOI~~

  • 相关阅读:
    ‘Host’ is not allowed to connect to this mysql server
    centos7安装mysql
    further configuration avilable 不见了
    Dynamic Web Module 3.0 requires Java 1.6 or newer
    hadoop启动 datanode的live node为0
    ssh远程访问失败 Centos7
    Linux 下的各种环境安装
    Centos7 安装 python2.7
    安装scala
    Centos7 安装 jdk 1.8
  • 原文地址:https://www.cnblogs.com/mrclr/p/9544749.html
Copyright © 2011-2022 走看看