时间复杂度

(涉及算法:模拟)

【问题描述(简要)】

小明写了好多循环并给出了时间复杂度,判断小明给出的时间复杂度是否正确。循环结构如下:

F i x y
循环体
E

其中“F i x y”表示
新建变量 i(变量 i 不可与未被销毁的变量重名)
初始化为 x
然后判断 i 和 y 的大小关系,若 i小于等于 y 则进入循环,否则不进入。
每次循环结束后 i都会被修改成i+1。

x 和 y 可以是正整数(x 和 y 的大小关系不定)或变量 n。
n 是一个变量,在时间复杂度计算中需保留该变量而不能将其视为常数,该数远大于 100。
“E”表示循环体结束。循环体结束时,这个循环体新建的变量也被销毁。

【输入格式】

输入文件名为 complexity.in。
输入文件第一行一个正整数 t,表示有 t(t≤10)个程序需要计算时间复杂度。
每个程序我们只需抽取其中“F i x y”和“E”即可计算时间复杂度。注意:循环结构允许嵌套。
每个程序的第一行包含正整数 L 和一个字符串,L代表程序行数,字符串表示这个程序的复杂度:
O(1) 表示常数复杂度, O(n^w) 表示复杂度为 n^w,w <= 100 ,保证复杂度只有 O(1)和 O(n^w) 两种类型。
接下来 L 行代表程序中循环结构中的“F i x y”或者“E”。
程序行若以“F”开头,表示进入一个循环,之后有空格分离的三个字符(串) i x y,其中 i 是一个小写字母(保证不为“n”),表示新建的变量名,x 和 y 可能是正整数或 n ,已知若为正整数则一定小于 100。
程序行若以“E”开头,则表示循环体结束。

【输出格式】

输出文件名为 complexity.out。
输出文件共 t行,对应输入的 t 个程序,每行输出“Yes”或“No”或者“ERR”(输出中不包含引号)
若程序实际复杂度与输入给出的复杂度一致则输出“Yes”,不一致则输出“No”,
若程序有语法错误则输出“ERR”。
① F 和 E 不匹配
②新建的变量与已经存在但未被销毁的变量重复两种情况)
注意:即使在程序不会执行的循环体中出现了语法错误也会编译错误,要输出“ERR”。

【样例 】

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

Yes
Yes
ERR
Yes
No
Yes
Yes
ERR

【样例说明】

第一个程序 i从 1 到 1是常数复杂度。
第二个程序 x 从 1 到 n 是 n 的一次方的复杂度。
第三个程序有一个 F 开启循环却没有 E 结束,语法错误。
第四个程序二重循环,n 的平方的复杂度。
第五个程序两个一重循环,n 的一次方的复杂度。
第六个程序第一重循环正常,但第二重循环开始即终止(因为 n 远大于 100,100 大于 4)。
第七个程序第一重循环无法进入,故为常数复杂度。
第八个程序第二重循环中的变量 xx 与第一重循环中的变量重复,出现语法错误②,输出 ERR。

【数据规模与约定】

对于 30%的数据:不存在语法错误,数据保证每个程序的前 L2 行一定为以 F 开头的语句,第 L2+1 行至第 L行一定为以 E 开头的语句,L≤10,若 x、y 均为整数,x 一定小于 y,且只有 y 有可能为 n。
对于 50%的数据:不存在语法错误,L≤100,若 x、y 均为整数,x 一定小于 y,且只有 y 有可能为 n。
对于 70% 的数据:不存在语法错误,L≤100。
对于 100% 的数据:L≤100。
时间限制:1s
空间限制:256MB

【题解】

感觉我的代码挺短的……(他们说长)
主要讲一下思路,具体做法注释在代码里面。
这是一个关于循环的复杂度的问题。 首先分析答案,答案有三种情况:
1.答案正确

2.答案错误
那么必然要存下小明的答案,用num1,再用ans表示正确复杂度
因为复杂度只有O(1)和O(n^w )两种情况,所以用0表示O(1),正整数w表示O(n^w)

3.程序错误
需要一个bool来判断指针是否错误,如果错误,只需输入数据后退出就可以,用flag
程序错误又分两种情况
① F 和 E 不匹配
sum1sum2记下两者的数量,最后判断两者数量是否相同即可
也可以用一个sum记录,最后判断它是否大于0即可
②新建的变量与已经存在但未被销毁的变量重复两种情况
那么就需要一个bool数组psx来表示这个变量是否已经存在
众所周知,循环是一层一层跳出去的,所以这个变量必然是存在顺序的,再用chan数组记录变量的顺序,方便退出循环时对变量进行撤回操作。
注意:即使在程序不会执行的循环体中出现了语法错误也会编译错误,要输出“ERR”。
这句话提醒我们会出现循环不进入的情况。
如果一层循环没有进入,那么它下面包含的所有循环都不会进入,也就不需要对他们进行操作。
用一个fl来记录没有进入的循环有几层,如果轮到一层循环时,fl不为0,那么这层循环必然也没有进入。遇到一个不能进入的循环就fl++,遇见一个E,退出了一层不进入的循环,就fl- -。
又因为即使在程序不会执行的循环体中出现了语法错误也会编译错误,所以把对变量重名的判断放在对不进入循环的判断前面就可以了。

然后对循环的情况进行判断,用一个zz来记录循环的复杂度
1.常数小——常数大
复杂度是O(1),因为O(1)表示为0.
这时候这个循环是有效的,但是它不会对复杂度产生影响,我们令mm++;
mm有什么用,下面会详细说。
2.常数大——常数小
这个循环不进入,使fl++
3.常数——n
复杂度多了一个n,zz++
4.n——常数
这个循环不进入,使fl++

以上是碰到F的做法

如果碰上E,需要做三件事
1.变量使用的撤回,将最后那个循环使用的变量记录为没有使用
2.如果fl不为0,使fl- -
3.如果zz不为0,对正确答案ans进行更新。
如果mm为0,zz- -,这里zz不清零,因为只是退出了一层循环
如果mm不为0,就表示上一层是(常数小——常数大)的循环
它的存在并没有对复杂度有影响,即zz 并没有因为这个循环而加1,所以这个E退出的时候,zz并不会减1.

思考完了,代码实现就不难了,注意一些小细节即可,尤其是字符串转成数字

关于mm的问题是salt___fish提出的,以下数据可以卡走没有mm的代码
1
10
O(n^3)
F i 1 n
F k 3 10
E
F j 2 n
F k 3 10
E
F k 3 n
E
E
E

【代码】

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int t,l,zz,mm,ans,fl,num1,sum1,sum2,tot=0,x,y;
string s,s1,s2;
char ch,chan[105]={};
bool psx[100]={},flag;
void clean(){flag = 1;//判断代码是否ERR,0是错误,1是正确num1 = 0;//记录小明自己的结果zz=0;//循环没有结束时记录复杂度的暂时容器mm=0;//记入有效但是不计入zz的常数到常数循环,防止将zz错减ans=0;//正确的复杂度fl=0;//判断没有进入的循环sum1=0;//F的数量sum2=0;//E的数量memset(psx,0,sizeof(psx));//用过的变量名tot = 0;
}
int main() {//freopen("complexity.in","r",stdin);//freopen("complexity.out","w",stdout);cin>>t;while(t--){clean();cin>>l>>s;if(l % 2) flag = 0;//如果代码长度是奇数,那么F与E的数量一定不一样,错误if(s.size() == 4) num1 = 0;//O(1)的情况else for(int i = 4; i < s.size()-1; i++)num1 = num1 * 10 + int(s[i] - '0');//因为w小于100,所以要用循环,我就摔在这while(l--){cin>>ch;if(ch == 'F'){sum1++;cin>>chan[++tot];//因为循环一层层退出,所以字母要有顺序if(psx[chan[tot]-'a'+1] == 1) flag = 0;//如果字母已出现,程序错误psx[chan[tot]-'a'+1] = 1;//记录字母cin>>s1>>s2;//输入字符串,因为x和y有可能是n,不能用int,char读不尽if(!flag) continue;//输入的都输入了,如果程序错误,退出继续输入if(fl){fl++;continue;}//如果上一层循环没有进入,那么这一层也一定没有进if(s1[0] == 'n' && s2[0] != 'n') {fl++;continue;}//因为n远大于吗100,循环不进去if(s1[0] != 'n' && s2[0] == 'n') zz++;//出现一层n,zz++(这里的1是指n的次方加一)if(s1[0] != 'n' && s2[0] != 'n'){//如果两个常数if(s1.size() > s2.size()) {fl++;continue;}//不进入循环mm++;if(s1.size() == s2.size())for(int i = 0; i < s1.size(); i++){if(s1[i] > s2[i]) {mm--;fl++;continue;}if(s1[i] < s2[i]) break;}//比较大小,因为数不是一位数,要循环}}if(ch == 'E'){if(!flag) continue;//如果程序错误退出sum2++;psx[chan[tot--]-'a'+1] = 0;//字母可以用了if(fl){fl--;continue;}//如果程序没有进入的,就往外退if(zz > 0){ans = max(ans,zz);!mm ? zz-- : mm--;} //如果zz大于0,就更新ans,只是退出一层循环,所以zz--,而不是清零}}if(!flag || sum1 != sum2 || fl) printf("ERR\n");//如果程序错误,E和F数量不一样,没进入的程序还没有退出完else if(ans == num1) printf("Yes\n");//如果小明答案和正确答案一样else printf("No\n");}return 0;
}

NOIP2017时间复杂度相关推荐

  1. P3952 NOIP2017 时间复杂度

    写了两三个小时,麻烦倒是不麻烦,要考虑清楚,想全了 只过了样例提交是不是傻,要自己造数据 数据不大可以用STL 建议自己刚一下,不看代码 #include <iostream> #incl ...

  2. [NOIp2017] 时间复杂度

    NOIp 2017 D1T2 时间复杂度 洛谷 P3952 传送门 稍微压了压行,写到了60行&&1.3kb以内,感觉自己的写法还是很清晰很优秀的. 少量的特判,比别的代码简洁多了. ...

  3. NOIP2017时间复杂度(提高D1T2)

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

  4. 语法入门*算法入门题单

    作者:王清楚 链接:https://ac.nowcoder.com/discuss/817596?type=101&order=0&pos=1&page=4&chann ...

  5. 【新手上路】语法入门算法入门题单

    作者:王清楚 链接:[新手上路]语法入门&算法入门题单_ACM竞赛_ACM/CSP/ICPC/CCPC/比赛经验/题解/资讯_牛客竞赛OJ_牛客网 来源:牛客网 介绍:本题单分为语法入门和算法 ...

  6. OI每周刷题记录——lrllrl

    看这标题就知道我是模仿的hzwer大佬,远程%%% 大佬的OI经历让蒟蒻我深受感触,为了晚一些AFO本蒟蒻也得加油了 从高二上期第一周开始计数,每个星期天更一次,一直更到我AFO 如果这是我此生最后一 ...

  7. [NOIP2017 提高组] 时间复杂度

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

  8. JZOJ 5474. 【NOIP2017提高组正式赛】时间复杂度

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

  9. 【NOIP2017】时间复杂度

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

  10. 『宝藏 状态压缩DP NOIP2017』

    宝藏(NOIP2017) Description 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的m 条道路和它们的长度. 小明决 ...

最新文章

  1. DBA入门之路:由浅入深的总结学习法
  2. 深入理解分布式技术 - 读写分离场景及注意事项解读
  3. 【UML】如何看Android的UML图
  4. Android官方开发文档Training系列课程中文版:管理Activity的生命周期之启动一个Activity
  5. Angular动态创建组件
  6. 用Linux命令行实现删除和复制指定类型的文件
  7. iOS多线程之GCD小记
  8. 《纽约邮报》手机客户端推送系统被黑 黑客发送抒情诗
  9. linux指定运行so文件,linux – 强制二进制文件使用特定(较新)版本的共享库(.so)...
  10. BurpSuite Pro 2021.2 最新版本
  11. 丹尼斯·里奇的自述简历
  12. material-table的使用
  13. 【hdu】6441 Find Integer - 费马大定理
  14. bugku 贝斯家族 (base91参照表)
  15. 从互联网角度出发,慧算账受客户追捧
  16. VUE页面背景设置为视频
  17. 这10本书,带你了解 ChatGPT 的底层逻辑!
  18. 实战-数据仓库构建(一)
  19. 青藤云——安全服务工程师面经(北京升鑫网络科技有限公司)
  20. SDK游戏盾有什么优势

热门文章

  1. SQL 获取本周日期
  2. DWGTool Acme CADSee 2020(cad看图软件)官方正式版V6.6.15.1366 | 好用免费的cad看图软件下载
  3. SAP学习记__物料管理(MM)模块__维护仓储地点
  4. 摇骰子、抽奖转盘酒桌游戏 人生重启模拟器小程序源码分享-开通流量主躺着赚钱
  5. 第1章 Linux内核概述
  6. uni-app 使用高德地图
  7. oracle erp 设置文档,Oracle ERP管理手册
  8. 《云计算核心技术剖析》读书笔记之一
  9. 淘宝新手开店从入门到精通→一路护航
  10. 模糊数学模型(一): 隶属函数、模糊集合的表示方法、模糊关系、模糊矩阵