目录
大意
求出不小于 n n 的所有完全平方数,
思路
算法一
自然,朴素的求法是直接一到n枚举,自然,这样的时间复杂度是 O(n) O ( n ) ,肯定超时。
算法二
用平方的方法优化一下,可将时间复杂度降至 O(n−−√) O ( n ) ,也就是看算到哪里的时候i的平方会超过n时停止。
算法三
完全平方数可以组成有规律的序列,例如
1,4,9,16,25,36,49,64,81…
1
,
4
,
9
,
16
,
25
,
36
,
49
,
64
,
81
…
可以发现这个序列相当于
1,1+3,1+3+5,1+3+5+7,1+3+5+7+9,1+3+5+7+11…
1
,
1
+
3
,
1
+
3
+
5
,
1
+
3
+
5
+
7
,
1
+
3
+
5
+
7
+
9
,
1
+
3
+
5
+
7
+
11
…
所以说,用这种规律去计算,时间复杂度为
O(n−−√)
O
(
n
)
。
有人会问:这样时间复杂度不是一样吗?有什么不一样呢?
答:因为C++中的加法运算比乘法运算要快得多,所以算法三的时间复杂度是优于算法二的。
代码
#include<cstdio>
using namespace std;
void write(int x)//输出流可以将代码从45ms优化至15ms
{
if(!x) return;else write(x/10);putchar(x%10+48);
}
int main()
{
int n,s,k=1;//s为当前要输出的数,k为累计的加数,自然也可以直接用公式2i-1代替k,不过我觉得用k还是更清晰点
scanf("%d",&n);s=1;
for(int i=1;s<=n;i++)
{
write(s);k+=2;s+=k;//加数累加,输出的数加上加数
if(i==9) {putchar(10);continue;}
if(i%10==9) {putchar(10);continue;}//这两个是换行处理,不是代码核心
putchar(32);//空格
}
}
代码2
#include<cstdio>
using namespace std;
void write(int x)
{
if(!x) return;else write(x/10);putchar(x%10+48);
}
int main()
{
int n,s=1;
scanf("%d",&n);
for(int i=2;s<=n;i++)
{
if(!((i-1)%10)) putchar(10);else if(i!=2) putchar(32);//换行处理,非代码核心
write(s),s+=(i<<1)-1;//这里的运算可以代替k
}
}