题目
题目背景
什么是时间复杂度?
在设计满足问题要求的算法时,复杂度的估算是非常重要的。我们不可能把每个想到的算法都去实现一遍看看是否足够快。应当通过估算算法的复杂度来判断所想的算法是否足够高效,能否通过题目的时间限制。
在分析复杂度时,我们通常考虑它与什么成正比,并称之为算法的阶。例如以下的程序段执行了四重循环,每重 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 n≤1000,将 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=1926≤106,故能通过。
样例二,该程序为二类,且 8 1 = 8 ≤ 1 0 7 8^1=8\leq10^7 81=8≤107,故能通过。
样例三,该程序为三类,且 1 7 4 = 83521 ≤ 1 0 8 17^4=83521\leq10^8 174=83521≤108,故能通过。
…
样例六,该程序为一类,且 120 7 4 = 2122409008801 > 1 0 6 1207^4=2122409008801>10^6 12074=2122409008801>106,故不能通过。
数据范围
1 ≤ T ≤ 5000 1 \leq T \leq 5000 1≤T≤5000
t y p e ∈ { 1 , 2 , 3 } type \in \{ 1, 2, 3 \} type∈{1,2,3}
1 ≤ a ≤ 5 1 \leq a \leq 5 1≤a≤5
0 ≤ N ≤ 3000 0 \leq N \leq 3000 0≤N≤3000
温馨提示
【温馨提示1】
C/C++语言中:
类型名称 | 字节数 | 最大值 |
---|---|---|
int | 4 | 2147483647 |
long long | 8 | 9223372036854775807 |
【温馨提示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;
}