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 }
類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 }
這裏給一個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 }
而後是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 }
最後是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 }
把三個程序分別運行一下,獲得三個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 }
windos下用 .//,linux下是 ~\\。
方便。
對拍講完啦~~~祝各位繼續AKIOI~~