例2-1 aabb
输出所有形如aabb的四位完全平方数
1 #include<stdio.h>
2 #include<math.h>
3 int main()
4 {
5 #if 0
6 //思路一 从aabb的可能性角度进行枚举
7 int a,b,temp;
8 for(a=1;a<=9;a++)
9 {
10 for(b=0;b<=9;b++)
11 {
12 temp=a*1000+a*100+b*10+b;
13 //temp=a*1100+b*11;更好
14 //先求出平方跟,再看它是否是整数:用一个数和它的整数部分比较就可以
15 float c=sqrt(temp);
16 if(c==floor(c+0.5))
17 printf("%d\n",temp);
18
19 }
20 }
21 #endif
22 #if 1
23 //思路二 枚举平方根a,从而避免开方操作
24 int a,b;
25 for(a=1;;a++)
26 {
27 b=a*a;//or use the pow function: pow(x,2)
28 if(b<1000) continue;
29 else if(b>9999) break;
30 else
31 {
32 int low, high;
33 low=b%100;
34 high=b/100;
35 if(((low%10)==(low/10))&&((high%10)==(high/10)))
36 printf("%d\n",b);
37 }
38 }
39
40
41
42 #endif
43 return 0;
44 }
注意:
1.floor(x)返回x的整数部分,
2.由于浮点数的计算(和函数)有可能存在一定的误差,所以改成四舍五入减小误差,用floor(x+0.5)和x比较!
3.由于 采用了条件continue 和break 所以 for的参数范围给是“残缺”的。
例题2-2.3n+1问题
对于任意大于1的自然数n,若n为奇数,则将n变为3n+1,否则变为n的一半。经过若干次变换,一定会使n变为1.输入n 输出变换次数。 n<10^9
1 #include<stdio.h>
2 int main()
3 {
4 #if 1
5 int n,count;
6 scanf("%d",&n);
7 if(n>1)
8 {
9 for(count=0;;count++){
10 if(n==1) break;
11 else
12 {
13 if(n%2==1) n=3*n+1;
14 else n=n/2;
15 }
16 }
17 }
18 printf("%d\n",count);
19 #endif
20 #if 0
21 int n,count=0;
22 scanf("%d",&n);
23 while(n>1)
24 {
25 if(n%2==1)
26 {
27 n=n*3+1;
28 printf("count=%d,n=%d",count,n);
29 }
30 else
31 {
32 n/=2;
33 printf("count=%d,n=%d",count,n);
34 }
35 count++;
36 }
37 printf("%d\n",count);
38 #endif
39 return 0;
40 }
注意:
这并不是真正那个的正确结果。比如输入987654321 采用第二段程序的时候结果是1 采用我的第一段程序的时候无法退出程序。
无法找出错误-> 调试! ->输出中间结果。
第二段代码的28行和33行 就是实例!
edward@edward:~/Desktop/Algorithm$ ./exa2-2
987654321
count=0,n=-13320043321
987654321虽然在n的范围内,但是乘法时候发生溢出!如做修改可以采用double型。
例题2-3.阶乘之和
输入n,计算S=1!+2!+3!+...+n!的末六位(不含前导0)。n<=10^6。
1 #include<stdio.h>
2 int main()
3 {
4 int i,j,n,temp=1;
5 long sum=0;
6 const int MOD =1000000;
7 scanf("%d",&n);
8 for(i=1;i<=n;i++)
9 {
10 temp=temp*i;
11 printf("current i is %d, value of i! is %d\n ",i,temp);
12 sum+=temp;
13 }
14 printf("%ld\n",sum%MOD);
15 return 0;
16 }
测试程序
在输入100 的时候,发现输出是负数! 通过打印中间结果发现又是乘法溢出了。
定理:计算只包含加法,减法和乘法的整数表达式除以正整数n的余数,可以在每步计算后对n取余,结果不变。
2 int main()
3 {
4 int i,j,n,temp=1;
5 long sum=0;
6 const int MOD =1000000;
7 scanf("%d",&n);
8 for(i=1;i<=n;i++)
9 {
10 temp=temp*i % MOD;
11 printf("current i is %d, value of i! is %d\n ",i,temp);
12 sum+=temp;
13 }
14 printf("%ld\n",sum % MOD);
15 return 0;
2 #include<time.h>
3 int main()
4 {
5 int i,j,n,temp=1;
6 long sum=0;
7 const int MOD =1000000;
8 scanf("%d",&n);
9 for(i=1;i<=n;i++)
10 {
11 temp=temp*i % MOD;
12 // printf("current i is %d, value of i! is %d\n ",i,temp);
13 sum+=temp;
14 }
15 printf("%ld\n",sum % MOD);
16 printf("Time used =%.2lf\n",(double)clock()/CLOCKS_PER_SEC);
17 return 0;
18 }
注意:
1.关于计时器函数 clock()的使用
该函数返回程序目前为止运行的时间,这样在程序结束之前调用它,便可获知整个程序的运行时间。
但是CLOCKS_PER_SEC常数与操作系统相关的值,不能直接使用clock()的返回值,需要除以CLOCKS_PER_SEC
2.为了不把键盘输入的时间计算在程序运行的时间内,需要使用管道符号输入
echo 20|./exa2-3
3.输入从40开始答案始终不变。通过中间结果可以发现这是因为25!末尾有6个0,所以从这项开始就不会影响后面的答案!
edward@edward:~/Desktop/Algorithm$ echo 20 |./exa2-3
820313
Time used =0.00
edward@edward:~/Desktop/Algorithm$ echo 40 |./exa2-3
940313
Time used =0.00
edward@edward:~/Desktop/Algorithm$ echo 160 |./exa2-3
940313
Time used =0.00
edward@edward:~/Desktop/Algorithm$ echo 10000 |./exa2-3
940313
Time used =0.00
edward@edward:~/Desktop/Algorithm$ echo 12800 |./exa2-3
940313
Time used =0.00
edward@edward:~/Desktop/Algorithm$ echo 51200 |./exa2-3
940313
Time used =0.00
edward@edward:~/Desktop/Algorithm$ echo 5120000 |./exa2-3
940313
Time used =0.04
对此,只需在for循环之前 加一句 if(n>25) n=25 即可解决效率和溢出问题!
事实上很多程序的运行时间与规模魔与n存在着近似的简单关系。
输出所有形如aabb的四位完全平方数
1 #include<stdio.h>
2 #include<math.h>
3 int main()
4 {
5 #if 0
6 //思路一 从aabb的可能性角度进行枚举
7 int a,b,temp;
8 for(a=1;a<=9;a++)
9 {
10 for(b=0;b<=9;b++)
11 {
12 temp=a*1000+a*100+b*10+b;
13 //temp=a*1100+b*11;更好
14 //先求出平方跟,再看它是否是整数:用一个数和它的整数部分比较就可以
15 float c=sqrt(temp);
16 if(c==floor(c+0.5))
17 printf("%d\n",temp);
18
19 }
20 }
21 #endif
22 #if 1
23 //思路二 枚举平方根a,从而避免开方操作
24 int a,b;
25 for(a=1;;a++)
26 {
27 b=a*a;//or use the pow function: pow(x,2)
28 if(b<1000) continue;
29 else if(b>9999) break;
30 else
31 {
32 int low, high;
33 low=b%100;
34 high=b/100;
35 if(((low%10)==(low/10))&&((high%10)==(high/10)))
36 printf("%d\n",b);
37 }
38 }
39
40
41
42 #endif
43 return 0;
44 }
注意:
1.floor(x)返回x的整数部分,
2.由于浮点数的计算(和函数)有可能存在一定的误差,所以改成四舍五入减小误差,用floor(x+0.5)和x比较!
3.由于 采用了条件continue 和break 所以 for的参数范围给是“残缺”的。
例题2-2.3n+1问题
对于任意大于1的自然数n,若n为奇数,则将n变为3n+1,否则变为n的一半。经过若干次变换,一定会使n变为1.输入n 输出变换次数。 n<10^9
1 #include<stdio.h>
2 int main()
3 {
4 #if 1
5 int n,count;
6 scanf("%d",&n);
7 if(n>1)
8 {
9 for(count=0;;count++){
10 if(n==1) break;
11 else
12 {
13 if(n%2==1) n=3*n+1;
14 else n=n/2;
15 }
16 }
17 }
18 printf("%d\n",count);
19 #endif
20 #if 0
21 int n,count=0;
22 scanf("%d",&n);
23 while(n>1)
24 {
25 if(n%2==1)
26 {
27 n=n*3+1;
28 printf("count=%d,n=%d",count,n);
29 }
30 else
31 {
32 n/=2;
33 printf("count=%d,n=%d",count,n);
34 }
35 count++;
36 }
37 printf("%d\n",count);
38 #endif
39 return 0;
40 }
注意:
这并不是真正那个的正确结果。比如输入987654321 采用第二段程序的时候结果是1 采用我的第一段程序的时候无法退出程序。
无法找出错误-> 调试! ->输出中间结果。
第二段代码的28行和33行 就是实例!
edward@edward:~/Desktop/Algorithm$ ./exa2-2
987654321
count=0,n=-13320043321
987654321虽然在n的范围内,但是乘法时候发生溢出!如做修改可以采用double型。
例题2-3.阶乘之和
输入n,计算S=1!+2!+3!+...+n!的末六位(不含前导0)。n<=10^6。
1 #include<stdio.h>
2 int main()
3 {
4 int i,j,n,temp=1;
5 long sum=0;
6 const int MOD =1000000;
7 scanf("%d",&n);
8 for(i=1;i<=n;i++)
9 {
10 temp=temp*i;
11 printf("current i is %d, value of i! is %d\n ",i,temp);
12 sum+=temp;
13 }
14 printf("%ld\n",sum%MOD);
15 return 0;
16 }
测试程序
在输入100 的时候,发现输出是负数! 通过打印中间结果发现又是乘法溢出了。
定理:计算只包含加法,减法和乘法的整数表达式除以正整数n的余数,可以在每步计算后对n取余,结果不变。
改进之:
2 int main()
3 {
4 int i,j,n,temp=1;
5 long sum=0;
6 const int MOD =1000000;
7 scanf("%d",&n);
8 for(i=1;i<=n;i++)
9 {
10 temp=temp*i % MOD;
11 printf("current i is %d, value of i! is %d\n ",i,temp);
12 sum+=temp;
13 }
14 printf("%ld\n",sum % MOD);
15 return 0;
16 }
为了观察程序运行的效率,引入一个“计时器”!
2 #include<time.h>
3 int main()
4 {
5 int i,j,n,temp=1;
6 long sum=0;
7 const int MOD =1000000;
8 scanf("%d",&n);
9 for(i=1;i<=n;i++)
10 {
11 temp=temp*i % MOD;
12 // printf("current i is %d, value of i! is %d\n ",i,temp);
13 sum+=temp;
14 }
15 printf("%ld\n",sum % MOD);
16 printf("Time used =%.2lf\n",(double)clock()/CLOCKS_PER_SEC);
17 return 0;
18 }
注意:
1.关于计时器函数 clock()的使用
该函数返回程序目前为止运行的时间,这样在程序结束之前调用它,便可获知整个程序的运行时间。
但是CLOCKS_PER_SEC常数与操作系统相关的值,不能直接使用clock()的返回值,需要除以CLOCKS_PER_SEC
2.为了不把键盘输入的时间计算在程序运行的时间内,需要使用管道符号输入
echo 20|./exa2-3
3.输入从40开始答案始终不变。通过中间结果可以发现这是因为25!末尾有6个0,所以从这项开始就不会影响后面的答案!
edward@edward:~/Desktop/Algorithm$ echo 20 |./exa2-3
820313
Time used =0.00
edward@edward:~/Desktop/Algorithm$ echo 40 |./exa2-3
940313
Time used =0.00
edward@edward:~/Desktop/Algorithm$ echo 160 |./exa2-3
940313
Time used =0.00
edward@edward:~/Desktop/Algorithm$ echo 10000 |./exa2-3
940313
Time used =0.00
edward@edward:~/Desktop/Algorithm$ echo 12800 |./exa2-3
940313
Time used =0.00
edward@edward:~/Desktop/Algorithm$ echo 51200 |./exa2-3
940313
Time used =0.00
edward@edward:~/Desktop/Algorithm$ echo 5120000 |./exa2-3
940313
Time used =0.04
对此,只需在for循环之前 加一句 if(n>25) n=25 即可解决效率和溢出问题!
事实上很多程序的运行时间与规模魔与n存在着近似的简单关系。