洛谷P3952 時間復雜度【字符串】【模擬】
題目描述
小明正在學習一種新的編程語言 A++,剛學會循環語句的他激動地寫了好多程序並 給出了他自己算出的時間復雜度,可他的編程老師實在不想一個一個檢查小明的程序, 於是你的機會來啦!下面請你編寫程序來判斷小明對他的每個程序給出的時間復雜度是否正確。
A++語言的循環結構如下:
F i x y
循環體
E
其中F i x y
表示新建變量 ii(變量 ii 不可與未被銷毀的變量重名)並初始化為 xx, 然後判斷 ii 和 yy 的大小關系,若 ii 小於等於 yy 則進入循環,否則不進入。每次循環結束後 ii 都會被修改成 i +1i+1,一旦 ii 大於 yy 終止循環。
xx 和 yy 可以是正整數(xx 和 yy 的大小關系不定)或變量 nn。nn 是一個表示數據規模的變量,在時間復雜度計算中需保留該變量而不能將其視為常數,該數遠大於 100100。
“E”表示循環體結束。循環體結束時,這個循環體新建的變量也被銷毀。
註:本題中為了書寫方便,在描述復雜度時,使用大寫英文字母“O”表示通常意義下“Θ”的概念。
輸入輸出格式
輸入格式:
輸入文件第一行一個正整數 tt,表示有 tt(t \le 10t≤10)個程序需要計算時間復雜度。 每個程序我們只需抽取其中 F i x y
和E
即可計算時間復雜度。註意:循環結構 允許嵌套。
接下來每個程序的第一行包含一個正整數 LL 和一個字符串,LL 代表程序行數,字符 串表示這個程序的復雜度,O(1)
表示常數復雜度,O(n^w)
表示復雜度為n^wnw,其 中w是一個小於100的正整數(輸入中不包含引號),輸入保證復雜度只有O(1)
O(n^w)
兩種類型。
接下來 LL 行代表程序中循環結構中的F i x y
或者 E
。 程序行若以F
開頭,表示進入一個循環,之後有空格分離的三個字符(串)i x y
, 其中 ii 是一個小寫字母(保證不為nn),表示新建的變量名,xx 和 yy 可能是正整數或 nn ,已知若為正整數則一定小於 100。
程序行若以E
開頭,則表示循環體結束。
輸出格式:
輸出文件共 tt 行,對應輸入的 tt 個程序,每行輸出Yes
或No
或者ERR
(輸出中不包含引號),若程序實際復雜度與輸入給出的復雜度一致則輸出Yes
,不一致則輸出No
,若程序有語法錯誤(其中語法錯誤只有: ① F 和 E 不匹配 ②新建的變量與已經存在但未被銷毀的變量重復兩種情況),則輸出ERR
註意:即使在程序不會執行的循環體中出現了語法錯誤也會編譯錯誤,要輸出 ERR
。
輸入輸出樣例
輸入樣例#1: 復制8 2 O(1) F i 1 1 E 2 O(n^1) F x 1 n E 1 O(1) F x 1 n 4 O(n^2) F x 5 n F y 10 n E E 4 O(n^2) F x 9 n E F y 2 n E 4 O(n^1) F x 9 n F y n 4 E E 4 O(1) F y n 4 F x 9 n E E 4 O(n^2) F x 1 n F x 1 10 E E輸出樣例#1: 復制
Yes Yes ERR Yes No Yes Yes ERR
說明
【輸入輸出樣例解釋1】
第一個程序 ii 從 1 到 1 是常數復雜度。
第二個程序 xx 從 1 到 nn 是 nn 的一次方的復雜度。
第三個程序有一個 F
開啟循環卻沒有 E
結束,語法錯誤。
第四個程序二重循環,nn 的平方的復雜度。
第五個程序兩個一重循環,nn 的一次方的復雜度。
第六個程序第一重循環正常,但第二重循環開始即終止(因為nn遠大於100,100大於4)。
第七個程序第一重循環無法進入,故為常數復雜度。
第八個程序第二重循環中的變量 xx 與第一重循環中的變量重復,出現語法錯誤②,輸出 ERR
。
【數據規模與約定】
對於 30\%30%的數據:不存在語法錯誤,數據保證小明給出的每個程序的前 L/2L/2 行一定為以 F
開頭的語句,第 L/2+1L/2+1 行至第 LL 行一定為以 EE 開頭的語句,L \le 10L≤10,若 xx、yy 均 為整數,xx 一定小於 yy,且只有 yy有可能為 nn。
對於 50\%50%的數據:不存在語法錯誤,L \le 100L≤100,且若 xx、yy 均為整數,xx 一定小於 yy, 且只有 yy 有可能為 nn。
對於 70\%70%的數據:不存在語法錯誤,L \le 100L≤100。
對於 100\%100%的數據:L \le 100L≤100。
如果需要Hack請私信@zhouyonglong或發討論,提供數據和能Hack掉的P3952或本題的AC記錄。
題意:
一個循環表示為$F i x y$其中$i$表示這一層循環的變量$x$表示循環開始的值$y$表示當變量小於等於$y$時始終執行循環
$E$是一層循環的結束標誌。
現在給定一段程序判斷這段程序的復雜度和給定的是否一致。
思路:
啊我好菜。剛開始思路不清晰對著樣例debug半天。
後來列了個表格分了情況稍微重新寫了一次,但是情況沒有考慮全面。
ERR的情況是,E和F的個數不匹配(計數)或外層循環和內層循環的變量名重復了(set和stack並用),比較好判斷。
當出現x是數字而y是n時,這層循環對復雜度有1的貢獻。
當出現數字數字和nn時,這層循環對復雜度沒有貢獻。
當出現n數字,或是x的數字比y的數字大的時候這層循環以及這層循環內部的循環都不會進入。
1 //#include<bits/stdc++.h> 2 #include<set> 3 #include<iostream> 4 #include<stdio.h> 5 #include<stdlib.h> 6 #include<cstring> 7 #include<stack> 8 #include<algorithm> 9 10 using namespace std; 11 12 int t, lines; 13 14 int getO(string s) 15 { 16 int i = 4, res = 0; 17 if(s[2] == ‘1‘)return 0; 18 while(s[i] != ‘)‘){ 19 res *= 10; 20 res += s[i] - ‘0‘; 21 i++; 22 } 23 return res; 24 } 25 26 int getnumber(string s) 27 { 28 int i = 0, len = s.length(); 29 int res = 0; 30 while(i < len){ 31 res *= 10; 32 res += s[i] - ‘0‘; 33 i++; 34 } 35 return res; 36 } 37 38 int main() 39 { 40 scanf("%d", &t); 41 while(t--){ 42 scanf("%d", &lines); 43 string O; 44 cin>>O; 45 46 stack<string>v_ar; 47 set<string>var; 48 int deep = 0, now = 0; 49 bool flag = true; 50 bool allone = false; 51 int EFs = 0; 52 for(int i = 0; i < lines; i++){ 53 char ch; 54 getchar(); 55 scanf("%c", &ch); 56 if(ch == ‘E‘){ 57 EFs -= 1; 58 now -= 1; 59 if(!v_ar.empty()){ 60 string v = v_ar.top();v_ar.pop(); 61 var.erase(v); 62 } 63 if(!EFs){ 64 allone = false; 65 now = 0; 66 //var.clear(); 67 } 68 } 69 else if(ch == ‘F‘){ 70 EFs += 1; 71 string v, x, y; 72 cin>>v>>x>>y; 73 if(var.find(v) != var.end())flag = false; 74 else{ 75 var.insert(v); 76 v_ar.push(v); 77 if(x[0] >= ‘0‘ && x[0] <= ‘9‘ && y[0] == ‘n‘){ 78 if(!allone)now += 1; 79 deep = max(deep, now); 80 } 81 else if(x[0] == ‘n‘ && y[0] >= ‘0‘ && y[0] <= ‘9‘ || getnumber(x) > getnumber(y))allone = true; 82 } 83 } 84 } 85 86 //cout<<deep<<endl; 87 if(EFs || !flag){ 88 printf("ERR\n"); 89 } 90 else if(getO(O) == deep){ 91 printf("Yes\n"); 92 } 93 else{ 94 printf("No\n"); 95 } 96 } 97 98 return 0; 99 }
洛谷P3952 時間復雜度【字符串】【模擬】