跟紫皮书走一遍|第二章

2-1 for:

tips:

  1. 在循环体里查看变量变化可以使用断点和watch功能。
  1. 缩短循环变量定义范围,如在for(int i = 0;xxxx;xxxx),在初始化部分就定义循环变量
1.aabb完全平方数:

输出形如aabb的4位完全平方数(n**2):

//方法一:

for(int i = 1; i <= 9; i++)
	for(int j = 0; j <= 9; j++){  //i的范围是1-9,j的范围是0-9 
		int n = i*1100 + j*11;	//n表示形如aabb的数
		int m = floor(sqrt(n) + 0.5);  //四舍五入
		if(m*m == n) printf("%d",n);
	}

解释:用n来表示形如aabb的数,m表示n开完平方根的整数,判断m*m是否=n

tips:

  • floor(x) 函数:返回不超过x的最大整数
  • floor( x + 0.5):四舍五入,相当于把一个单位区间在数轴上向右移动了0.5的距离,例如:floor(x)=1的区间为[1,2)
  • 浮点数运算可能存在误差,故进行浮点数比较时,一定要考虑误差。
//方法二:枚举平方根x

for(int x = 1; ; x++){
	int n = x*x;
	if(n < 1000) continue;
	if(n > 9999) break;  //确定四位数的范围
	int high = n / 100;   // aa
	int low = n % 100;  // bb
	if(high/10 == high%10 && low/10 == low%10) printf("%d",n); 
}

2-2while 和 do-while :

本小节介绍了循环结构的代价

最常见的两个问题:算术溢出程序效率低下。
最常用的两个工具:输出中间结果计时函数。(分别对应溢出检查和效率检查)

阶乘之和

输入n,计算S=1!+2!+3!+…+n!的末6位。n<=10**6

#include<stdio.h>
#include<time.h>

int main(){
	const int MOD = 1000000;
	int n, S = 0;
	scanf("%d",&n);
	for(int i = 1; i <= n; i++){
		int factorial = 1;
		for(int j = 1; j <= i; j++){
			factorial = (factorrial * j % MOD);
		}
		S  = (S +factorial) % MOD;
	}
	printf("time used = %.2f\n",(double)clock() / CLOCK_PER_SEC);// / CLOCK_PER_SEC代表单位为“秒”
}
/*clock() / CLOCK_PER_SEC:在程序结束之前调用此函数可以获得整个程序的运行时间,

减少程序运行时间的方法:
可知计算到25!时末尾有6个0,所以在第5项开始,后边所有项都不会影响末6位数字。–只需要在程序前加上 if(n > 25)n = 25;效率和溢出问题都会解决

2-3 竞赛中的输入和输出框架

tips:

  • 变量在未赋值之前,值是不确定的。所以声明时最好赋初值。
  1. 标准输入输出下的 结束输入
    Windows下,输入完毕后先按 Enter ,再按 Ctrl+Z ,最后再按Enter 可以结束输入。

  2. 务必了解比赛规定
    有的时候可以用文件来储存输入数据和输出数据,便于文件的比较。

需要注意文件读写规定
I/O方式(直接读键盘、写屏幕),还是文件输入输出
如果是文件输入输出,那是否禁止用重定向方式访问文件?


遵守文件名规定:
包括程序文件名和输入输出文件名。注意大小写,不要拼错文件名,不要使用相对路径或者绝对路径

数据统计:

输入一些整数,求他们的最小值,最大值和平均值(保留三位小数),输入的这些数是保证不超过1000的整数。

a.重定向版
#define LOCAL
#include<stdio.h>
#define INF 1000000000

int main(){
#ifdef LOCAL
	freopen("date.in","r",stdin);
	freopen("date.out","w".stdout);
#endif
	int x,n = 0, min = INF,max = -INF,s = 0;
	while (scanf("%d",&x) == 1){	//scanf()返回的是输入元素的个数,输入结束后无法再读取x,将返回0
		s += x;
		if(x < min) min = x;
		if(x > max) max = x;
	/*
		printf("x = %d, min =%d, max =%d",x,min,max);
	*/
		n++;
	}
	printf("%d %d %0.3f",min,max.(double)s/n);
}

  • #ifdef和#endif:重定向部分,含义是:只有定义了LOCAL符号才能进行读写。

  • 输出中间结果的printf部分可以写在注释里,需要用的时候只需要把注释符号删掉。

  • 把LOCAL符号写在首行,如果比赛要求读写标准输入输出,提交程序时方便删除。

    当然,注释掉要比定义LOCAL方便。

b.fopen版(若不让用重定向方式)
#include<stdio.h>
#define INF 1000000000

int main(){
	FILE *fin, *fout;
	fin = fopen("date.in","rb");
	fout = fopen("date.out","wb");

	int x,n = 0, min = INF,max = -INF,s = 0;
	while (fscanf(fin,"%d",&x) == 1){	
		s += x;
		if(x < min) min = x;
		if(x > max) max = x;
		n++;
	}
	fprintf(fout,"%d %d %0.3f\n",min,max.(double)s/n);
	fclose(fin);
	fclose(fout);
	
}
  1. 先声明变量fin和fout,
  2. 把scanf改成fscanf,并且第一个参数是fin;把printf改成fprintf,并且第一个参数为fout。
  3. 最后执行fclose关闭两个文件
c.两种方式的比较:
重定向fopen
简单繁琐
不能同时读写文件和用I/O灵活,可以反复打开读写文件
需要define符号;使用freopen;和stdin和stdout需要定义读文件写文件变量;使用fopen();输入输出时用fscanf、fprntf并且第一个参数为对应的变量;需要用fclose()关闭文件
不能用标准输入输出方式可以用,只需赋值fin=stdin;fout=stdout;另外不要调用fopen和fclose
多数据统计

指的是输入数据的文件里有多组数据
和上题一样,不过输入应包含多组数据,且输入整数 n=0 为输入结束标记,程序应当忽略这组数据,相邻两组数据间应输出一个空行。例如:

样例输入:
8
2 8 3 5 1 7 3 6
4
-4 6 10 0
样例输出:
case1:1 8 4.375
/空行/
case2:-4 10 3.000

#include<stdio.h>
#define INF 1000000000

int main(){
	int x,n = 0, min = INF,max = -INF,s = 0,kase = 0;//kase为“当前数据编号”计数器
	while (scanf("%d",&x) == 1 && n){	//&&n是因为 n=0是输入结束标记
		int s = 0;
		min = INF;
		max = -INF;	//	max和min重置,否则会影响下组数据求解
		for(int i = 0; i < n; i++){
			scanf("%d",&x);
			s += x;
			if(x < min) min = x;
			if(x > max) max = x;
		}
		if(kase) printf("\n");
		printf("case%d: %d %d %0.3f\n", ++kase,min,max.(double)s/n);
	}
  • 当嵌套内外有同名变量时,内层变量会屏蔽外层变量,有时会引起十分隐蔽的错误。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值