隨機數據生成與對拍【c++版,良心講解】

10.7更新:見最下面node

 

離NOIP2018沒剩多長時間了,我忽然發現我連對拍還不會,因而趕忙到網上找資料,找了半天發現了一個特別妙的程序,用c++寫的!linux

 

不過先講講隨機數據生成吧。ios

很簡單,就是寫一個程序模擬輸入數據,而後利用rand()編寫隨機數。c++

在頭文件cstdlib中,有rand(), srand()函數,以及常量RAND_MAX.git

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之間的整數。windows

srand(seed)函數接受一個unsigned int類型的參數seed,以seed爲「隨機種子」。bash

rand()函數基於線性同餘遞推式(就是某種遞推式吧~)生成隨機數,「隨機種子「至關於這個遞推式的初始參數,若不執行srand(),則種子默認爲1.dom

當種子肯定後,生成的隨機數列也是固定的,所以這種隨機方法是」僞隨機「,因此通常要在開始調用srand(),且以當前時間爲隨機種子。ide

怎麼寫呢?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\n", 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\n", 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\n",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\n"); return 0;
19         }
20         else printf("#%d AC %.2lfms\n", t, End - Beg);
21     }
22     return 0;
23 }
View Code

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

方便。

 

對拍講完啦~~~祝各位繼續AKIOI~~

相關文章
相關標籤/搜索