**链接 : ** Here!

**思路 : **

  • 这是一道大模拟, 区分好情况就没问题了

  • 循环构成部分 : $F , x , i , j$ 和 $E$ , 需要注意的是 $i , j$,

    1. - 分析 $i, j$ 的情况 :
    2. - $i, j$ 全为 $n$ 的时候, 复杂度为 $O(1)$
    3. - $i, j$ $number$ $n$ 的时候复杂度为 $O(n)$
    4. - $i, j$ $n$ $number$ 的时候复杂度为 $O(0)$
    5. - $i, j$ 全为 $number$ 时, 需要考虑
    6. - 如果 $i > j$ 复杂度为 $O(0)$
    7. - 否则复杂度为 $O(1)$
  • 分析多个循环的复杂度情况 :

    - 首先分析循环内外层嵌套的复杂度情况 :

    1. - | 外层复杂度 \\ 内层复杂度 | O(0) | O(1) | O($n^{w_2}$) |
    2. | -------------- | ------------ | ------------ | ------------------------------------ |
    3. | O(0) | O(0) | O(0) | O(0) |
    4. | O(1) | O(1) | O(1) | O(n) |
    5. | O($n^{w_1}$) | O($n^{w_1}$) | O($n^{w_1}$) | multiply(O($n^{w_1}$), O($n^{w_2}$)) |
    6. - 然后**分析循环并列**的复杂度情况 : **选取并列复杂度较大的那个**
  • 错误情况 :

    - $F$ 和 $E$ 不匹配

    - 预期复杂度与实际复杂度不匹配

  • 分析完成之后直接敲代码就$ok$了, 如果我们将整个大的循环嵌套并列的结构抽象成一棵树的话, 那就会发现, 必须存一下当前层的最大复杂度

代码 :

  1. /*************************************************************************
  2. > File Name: 时间复杂度.cpp
  3. > Author:
  4. > Mail:
  5. > Created Time: 2017年11月22日 星期三 18时26分04秒
  6. ************************************************************************/
  7. #include <cstdio>
  8. #include <iostream>
  9. #include <string>
  10. #include <stack>
  11. using namespace std;
  12. struct expr {
  13. char var; // 记录变量名
  14. string st, ed; // 记录循环的开始终止位置
  15. string tempO; // 记录复杂度
  16. string nowLayerO; // 记录当前层的最大复杂度
  17. };
  18. int T, n;
  19. string des; // 记录预测复杂度
  20. int calNumber(const string &str) {
  21. int temp = 0;
  22. for (int i = 0 ; i < str.length() ; ++i) {
  23. temp = temp * 10 + str[i] - '0';
  24. }
  25. return temp;
  26. }
  27. // 计算复杂度
  28. void calComplexity(expr &exp) {
  29. // case 1 : 如果st,ed全为n的话
  30. if (exp.st == "n" && exp.ed == "n") {
  31. exp.tempO = "1";
  32. return;
  33. }
  34. // case 2 : 如果st为数字,ed为n
  35. if (exp.st != "n" && exp.ed == "n") {
  36. exp.tempO = "n";
  37. return;
  38. }
  39. // case 3 : 如果st为n,ed为数字
  40. if (exp.st == "n" && exp.ed != "n") {
  41. exp.tempO = "0";
  42. return;
  43. }
  44. // case 4 : 如果st,ed全为数字且st <= ed
  45. // case 5 : 如果st,ed全为数字且st > ed
  46. int st_num = calNumber(exp.st);
  47. int ed_num = calNumber(exp.ed);
  48. if (st_num <= ed_num) {
  49. exp.tempO = "1";
  50. } else {
  51. exp.tempO = "0";
  52. }
  53. return;
  54. }
  55. // 计算str中的幂指数, str为n^w(w >= 1),当w为1的时候是可以省略的
  56. int calExponent(const string &str) {
  57. // 特殊情况
  58. if (str == "n") {
  59. return 1;
  60. }
  61. int ret = 0;
  62. for (int i = 2 ; i < str.length() ; ++i) {
  63. ret = ret * 10 + str[i] - '0';
  64. }
  65. return ret;
  66. }
  67. // 复杂度相乘
  68. // 如果外层循环是O(0)那么a * b -> O(0)
  69. // 如果内层循环是O(0)那么a * b -> a的复杂度
  70. // a代表外层复杂度, b代表内层复杂度
  71. string multiComplexity(const string &a, const string &b) {
  72. string ret = "";
  73. if (a == "0") {
  74. ret = "0";
  75. } else if (a == "1") {
  76. if (b == "0") {
  77. ret = "1";
  78. } else {
  79. ret = b;
  80. }
  81. } else {
  82. if (b == "0") {
  83. ret = a;
  84. } else if (b == "1") {
  85. ret = a;
  86. } else {
  87. // 如果能进入这里首先可以确定a,b为n^w
  88. // 且a,b的w >= 1因此tstr直接写个前缀n^是完全没问题的
  89. int expon1 = calExponent(a);
  90. int expon2 = calExponent(b);
  91. string tstr1 = "n^";
  92. string tstr2 = "";
  93. expon1 += expon2;
  94. while (expon1) {
  95. tstr2 += (char)((expon1 % 10) + '0');
  96. expon1 /= 10;
  97. }
  98. for (int i = tstr2.length() - 1 ; i >= 0 ; --i) {
  99. tstr1 += tstr2[i];
  100. }
  101. ret = tstr1;
  102. }
  103. }
  104. return ret;
  105. }
  106. // 复杂度相加,选出复杂度较大的那个
  107. string addComplexity(const string &a, const string &b) {
  108. string ret = "";
  109. if (a == "0") {
  110. ret = b;
  111. } else if (a == "1") {
  112. ret = (b == "0" ? a : b);
  113. } else {
  114. if (b == "0" || b == "1") {
  115. ret = a;
  116. } else {
  117. int expon1 = calExponent(a);
  118. int expon2 = calExponent(b);
  119. ret = (expon1 > expon2 ? a : b);
  120. }
  121. }
  122. return ret;
  123. }
  124. void read() {
  125. scanf("%d", &T);
  126. while (T--) {
  127. int vis[30] = {0}, flag = 0; // 标记是否出现变量名冲突
  128. cin >> n >> des;
  129. expr exp[n];
  130. stack<expr> myStack;
  131. string sum = "0";
  132. string maxO = "0";
  133. for (int i = 0 ; i < n ; ++i) {
  134. char firstCh;
  135. cin >> firstCh;
  136. if (firstCh != 'E') {
  137. cin >> exp[i].var >> exp[i].st >> exp[i].ed;
  138. if (vis[exp[i].var - 'a']) {
  139. flag = 1;
  140. }
  141. vis[exp[i].var - 'a'] = 1;
  142. calComplexity(exp[i]);
  143. // cout << "exp.tempO : " << exp[i].tempO << endl;
  144. exp[i].nowLayerO = exp[i].tempO;
  145. myStack.push(exp[i]);
  146. } else {
  147. // 如果遇到E则该弹栈计算了
  148. // 并且更新新栈顶当前层数最大复杂度
  149. // 如果空栈还弹,那说明ERR
  150. if (myStack.empty()) {
  151. flag = 1;
  152. continue;
  153. }
  154. expr topExp = myStack.top();
  155. myStack.pop();
  156. vis[topExp.var - 'a'] = 0;
  157. // 先获取当弹出的当前层最大复杂度
  158. string temp1 = topExp.nowLayerO;
  159. // 暂存一下当前最大复杂度
  160. maxO = topExp.nowLayerO;
  161. // 如果能向上更新这个最大复杂度
  162. if (!myStack.empty()) {
  163. topExp = myStack.top();
  164. myStack.pop();
  165. topExp.nowLayerO = addComplexity(topExp.nowLayerO, multiComplexity(topExp.tempO, temp1));
  166. myStack.push(topExp);
  167. }
  168. // cout << " maxO : " << maxO << endl;
  169. }
  170. // 如果栈为空,那么说一个loop已经结束了
  171. if (myStack.empty()) {
  172. sum = addComplexity(sum, maxO);
  173. maxO = "0";
  174. }
  175. }
  176. if (flag || !myStack.empty() || (n & 1)) {
  177. printf("ERR\n");
  178. } else {
  179. // cout << "ans : " << sum << endl;
  180. if (sum == "n") sum = "n^1";
  181. if (sum == "0") sum = "1";
  182. sum = "O(" + sum + ")";
  183. if (sum == des) {
  184. printf("Yes\n");
  185. } else {
  186. printf("No\n");
  187. }
  188. }
  189. }
  190. }
  191. int main() {
  192. read();
  193. return 0;
  194. }

计蒜客 时间复杂度 (模拟) & 洛谷 P3952 时间复杂度的更多相关文章

  1. 洛谷 P3952 时间复杂度 解题报告

    P3952 时间复杂度 题目描述 小明正在学习一种新的编程语言A++,刚学会循环语句的他激动地写了好多程序并 给出了他自己算出的时间复杂度,可他的编程老师实在不想一个一个检查小明的程序, 于是你的机会 ...

  2. 洛谷 - P3952 - 时间复杂度 - 模拟

    https://www.luogu.org/problemnew/show/P3952 这个模拟,注意每次进入循环的时候把新状态全部入栈,退出循环的时候就退栈. 第一次就错在发现ERR退出太及时,把剩 ...

  3. 洛谷P3952 时间复杂度【字符串】【模拟】

    题目描述 小明正在学习一种新的编程语言 A++,刚学会循环语句的他激动地写了好多程序并 给出了他自己算出的时间复杂度,可他的编程老师实在不想一个一个检查小明的程序, 于是你的机会来啦!下面请你编写程序 ...

  4. 2018.11.02 洛谷P3952 时间复杂度(模拟)

    传送门 惊叹考场dubuffdubuffdubuff. 这题还没有梭哈难啊233. 直接按照题意模拟就行了. 代码: #include<bits/stdc++.h> using names ...

  5. 洛谷P3952 时间复杂度(模拟)

    题意 题目链接 Sol 咕了一年的题解..就是个模拟吧 考场上写的递归也是醉了... 感觉一年自己进步了不少啊..面向数据编程的能力提高了不少 #include<bits/stdc++.h> ...

  6. 洛谷 P3952 时间复杂度【模拟】

    把No写成NO,WA了一发-- 现在看这题也不难-- 用一个栈,记一下前面F的字母,是否合法,合法的有多长,每次入栈弹栈即可 #include<iostream> #include< ...

  7. 洛谷P3952 时间复杂度

    大毒瘤...... 时隔快半年我终于花了两个小时堪堪A掉这一题...果然我还没有准备好. 想法:用DFS模拟递归. 时间复杂度的处理:每层循环取max,然后相加. 最大难点:各种繁杂而令人发指的特判. ...

  8. 洛谷 P3952时间复杂度 (本地AC测评RE的伪题解)

    [题目描述] 小明正在学习一种新的编程语言 A++,刚学会循环语句的他激动地写了好多程序并 给出了他自己算出的时间复杂度,可他的编程老师实在不想一个一个检查小明的程序, 于是你的机会来啦!下面请你编写 ...

  9. 计蒜客NOIP模拟赛6 D1T1Diamond-square

    Diamond-square 算法是一种能够用于生成噪声的算法,现在我们考虑这个算法的一个变种. 你有一个 2^n\times 2^n2​n​​×2​n​​ 的网格,一共有 (2^n+1)^2(2​n ...

随机推荐

  1. js setTimeout函数

    最近在看JS DOM编程艺术,在第十章的动画里面有个setTimeout函数的例子中涉及了很多的引号,研究了好大一会才看明白,综合网上各个大神的解释和自己的理解,其原理是这样的: 首先看下程序源代码: ...

  2. MySQL必知必会面试题 基础

    1.登录数据库 (1).单实例 mysql -uroot -poldboy (2).多实例 mysql -uroot -poldboy -S /data/3306/mysql.sock 2.查看数据库 ...

  3. 利用junit对springMVC的Controller进行测试

    本文转自http://www.tuicool.com/articles/7rMziy 平时对junit测试service/DAO层已经很熟悉不过了,如果不了解,可以猛戳这里,但是我们要测试contro ...

  4. SPOJ 1771&&DLX精确覆盖,重复覆盖

    DLX的题,做过这题才算是会吧. 这道题转化成了精确覆盖模型来做,一开始,只是单纯的要覆盖完行列和斜线,WA. 后来醒悟了,不能这样,只要覆盖全部行或列即可.虽然如此,但某些细节地方很关键不能考虑到. ...

  5. Android之——自己主动挂断电话的实现

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47072451 通过<Android之--AIDL小结>与<And ...

  6. hadoop-2.6.0集群开发环境配置

    hadoop-2.6.0集群开发环境配置 一.环境说明 1.1安装环境说明 本例中,操作系统为CentOS 6.6, JDK版本号为JDK 1.7,Hadoop版本号为Apache Hadoop 2. ...

  7. Dozer--第三方复制工具,哎哟,还不错!

    Dozer简单点说,就是拷贝工具,也是复制工具的意思,官方的解释是:Dozer is a Java Bean to Java Bean mapper that recursively copies d ...

  8. 【网络协议】ICMP协议、Ping、Traceroute

        ICMP协议 ICMP常常被觉得是IP层的一个组成部分,它是网络层的一个协议.它传递差错报文以及其它须要注意的信息.ICMP报文通常被IP层或更高层(TCP.UDP等)使用,它是在IP数据报内 ...

  9. spring 获取对象方式

    1 通过配置文件注入 1.配置文件里配置注入信息 2.class中加入注解的接口(set get. 构造函数等) 2.通过注解方式获得 1. 在class中对方法加入注解信息 (类标示 :@Servi ...

  10. B1108 [POI2007]天然气管道Gaz 贪心

    啊啊啊,这题有毒.我想了各种花式数据结构,最后告诉我贪心???受不了... 题干: Description Mary试图控制成都的天然气市场.专家已经标示出了最好的天然气井和中转站在成都的地图.现在需 ...