【QED】科普时间到Ⅰ:估算时间复杂度

题目

题目背景

什么是时间复杂度?

在设计满足问题要求的算法时,复杂度的估算是非常重要的。我们不可能把每个想到的算法都去实现一遍看看是否足够快。应当通过估算算法的复杂度来判断所想的算法是否足够高效,能否通过题目的时间限制。

在分析复杂度时,我们通常考虑它与什么成正比,并称之为算法的阶。例如以下的程序段执行了四重循环,每重 n n n次,则它的运行时间与 f ( n ) = n 4 f(n)=n^4 f(n)=n4成正比。我们将与 f ( n ) f(n) f(n)成正比的时间复杂度写作 O ( f ( n ) ) O(f(n)) O(f(n)),将对应的运行时间写作 O ( f ( n ) ) O(f(n)) O(f(n))时间。例如下面这个程序段的时间复杂度就是 O ( n 4 ) O(n^4) O(n4)

int n = 100;
unsigned long long sum = 0;
for(int i=1; i<=n; i++)
	for(int j=1; j<=n; j++)
		for(int x=1 ;x<=n; x++)
			for(int y=1; y<=n; y++)
				sum+=y;

关于运行时间

程序的运行时间不光取决于复杂度,也会受诸如循环体的复杂性等因素的影响。但是,因此造成的差距多数情况下最多也就几十倍。另一方面,忽略其余因素, n = 1000 n=1000 n=1000时, O ( n 4 ) O(n^4) O(n4)时间的算法和 O ( n 2 ) O(n^2) O(n2)时间的算法的差距就是足足一百万倍!因此要缩短程序的运行时间,主要应该从复杂度入手。

估算出算法的复杂度后,只要将 n n n可能的最大值代入复杂度的渐近式 f ( n ) f(n) f(n)中,就能简单地判断算法是否能够满足运行时间限制的要求。例如,考虑 O ( n 2 ) O(n^2) O(n2)时间的算法,假设题目描述中的限制条件为 n ≤ 1000 n \leq 1000 n1000,将 n n n的最大可能取值 N = 1000 N=1000 N=1000代入 n 2 n^2 n2就得到了 f ( n ) ≤ 1000000 f(n) \leq 1000000 f(n)1000000。在这个数值的基础上,假设题目时间限制为 1 s 1s 1s,我们就可以结合下表判断了。

f ( n ) ≈ 1 0 6 f(n) \approx 10^6 f(n)106游刃有余
f ( n ) ≈ 1 0 7 f(n) \approx 10^7 f(n)107勉勉强强
f ( n ) ≈ 1 0 8 f(n) \approx 10^8 f(n)108很悬,仅限循环体非常简单的情况

——摘编自《挑战程序设计竞赛(第2版)》[日] 秋叶拓哉等

题目描述

了解了上述关于时间复杂度的知识后,你决定编写一个简易的测评程序,实现根据一个程序的时间复杂度估算它是否能够通过某题目的功能。

为了简化问题,我们约定待测程序的复杂度渐进式 f ( n ) f(n) f(n)均为关于 n n n的幂函数 n a n^a na,并规定:

对一类程序当且仅当 f ( n ) ≤ 1 0 6 f(n) \leq 10^6 f(n)106时能通过;

对二类程序当且仅当 f ( n ) ≤ 1 0 7 f(n) \leq 10^7 f(n)107时能通过;

对三类程序当且仅当 f ( n ) ≤ 1 0 8 f(n) \leq 10^8 f(n)108时能通过;

对于 f ( n ) > 1 0 8 f(n) > 10^8 f(n)>108的情况,任何程序都将不能通过。

现在你已知某题目中 n n n的最大取值、待测程序的复杂度以及它的类型,请你判断它是否能够通过题目。

输入格式

本题有多组测试样例。输入的第一行仅含一个正整数 T T T,代表测试样例的数量。

接下来共 T T T行,每行为一组,共 T T T组。对于每一组测试样例,将在一行内依次给出一个正整数 t y p e type type,一个正整数 a a a,和一个整数 N N N。它们之间用一个英文空格字符分隔。

其中 t y p e type type表示待测程序的类型, a a a表示待测程序的时间复杂度渐进式中幂函数的指数, N N N表示题目中 n n n的最大取值。数据范围见题目末尾。

输入数据不含行末空格和文末空行。

输出格式

输出共 T T T行,每行一个字符串"Yes"或"No",代表该组测试样例的答案。当待测程序能通过题目时,输出"Yes"。反之,输出"No"。

请勿输出行末空格和引号,并注意大小写区分。

测试样例

6
1 1 1926
2 1 8
3 4 17
3 5 0
3 1 2333
1 4 1207
Yes
Yes
Yes
Yes
Yes
No

样例说明

在上述样例组中,共有 T = 6 T=6 T=6组测试样例。

样例一,该程序为一类,且 192 6 1 = 1926 ≤ 1 0 6 1926^1=1926\leq10^6 19261=1926106,故能通过。

样例二,该程序为二类,且 8 1 = 8 ≤ 1 0 7 8^1=8\leq10^7 81=8107,故能通过。

样例三,该程序为三类,且 1 7 4 = 83521 ≤ 1 0 8 17^4=83521\leq10^8 174=83521108,故能通过。

样例六,该程序为一类,且 120 7 4 = 2122409008801 > 1 0 6 1207^4=2122409008801>10^6 12074=2122409008801>106,故不能通过。

数据范围

1 ≤ T ≤ 5000 1 \leq T \leq 5000 1T5000

t y p e ∈ { 1 , 2 , 3 } type \in \{ 1, 2, 3 \} type{1,2,3}

1 ≤ a ≤ 5 1 \leq a \leq 5 1a5

0 ≤ N ≤ 3000 0 \leq N \leq 3000 0N3000

温馨提示

【温馨提示1】

C/C++语言中:

类型名称字节数最大值
int42147483647
long long89223372036854775807

【温馨提示2】

每种编程语言都有其长处和短处。对于ACM-ICPC等程序设计竞赛而言,通常允许使用的语言有C/C++、Python和Java。但综合考量各语言优缺点(特别是考虑到Python和Java运行速度慢这一劣势),主流选用的语言一般为C++,只有在特定题目上会选用Python或Java实现。

某种意义上,在相同的算法时间复杂度和实现思路前提下,选用C/C++编写的程序是本题中提到的“一类程序”,而Python或Java编写的程序则是“二、三类程序”。

【温馨提示3】

与绝大多数ACM-ICPC/CCPC比赛类似,本场比赛中,题目并非按照前易后难的难易度排序。难题可能出现在较前的位置,容易的题目也可能出现在末尾。(本题定位为简单题)

思路

一个比较简单的模拟题目,注意一下幂运算之后的结果会不会超范围

核心代码

void solve()
{
    int s;
    cin>>s;
    long long n,a;
    cin>>a>>n;
    long long zhi;
    if(s==1)zhi=1e6;
    if(s==2)zhi=1e7;
    if(s==3)zhi=1e8;
    if(pow(n,a) <= zhi)
        cout<<"Yes"<<endl;
    else
        cout<<"No"<<endl;
}
  • 25
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

想要AC的dly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值