算法竞赛入门经典 第2章 习题答案

本文提供了算法竞赛入门经典第2章的习题解答,包括位数计算、水仙花数、韩信点兵问题、倒三角形绘制、统计数值、求和计算、π的近似计算、子序列和、分数转小数以及数字排列问题。通过这些习题,读者可以提升C语言编程和算法解决实际问题的能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原书注:本章题目需用文件输入输出。


习题2-1 位数

输入一个不超过10的9次方的正整数,输出它的位数。例如:12735的位数是5,。请不要使用任何数学函数,只用四则运算和循环语句实现。

重定向:

#include<stdio.h>
int main()
{
freopen('xt2-1.in', 'r', stdin);
freopen('xt2-1.out', 'w', stdout);
int i, m, n;
while(scanf('%d', &n) == 1)
{
m = 0;
for (i = 1; i <= 1000000000; i *= 10)
if (n / i > 1) m++;
printf('%d\n', m);
}
return 0;
}
fopen:
#include<stdio.h>
int main()
{
	FILE *fin, *fout;
	fin = fopen("xt2-1.in", "rb");
	fout = fopen ("xt2-1.out", "wb");
	//freopen("xt2-1.in", "r", stdin);
	//freopen("xt2-1.out", "w", stdout);
	int i, m, n;
	while(fscanf(fin,"%d", &n) == 1)
	{
	m = 1;
	for (i = 1; i <= 1000000000; i *= 10)
		if (n / i > 1) m++;
	fprintf(fout,"%d\r\n", m);

	}
	fclose(fin);
	fclose(fout);
	return 0;
}


习题2-2 水仙花数

输出100-999中的所有水仙花数。若3位数ABC满足ABC=A^3+B^3+C^3,则称其为水仙花数。例如 153= 1^3+5^3+3^3 ,所以153是水仙花数。

重定向:

#include<stdio.h>
int main()
{
	int i, a, b, c;
	//freopen("xt2-2.in", "r", stdin);
	freopen("xt2-2.out", "w", stdout);
	for (i = 100; i <= 999; i++)
		{
			a = i/100;
			b = i/10 - a*10;
			c = i - a*100 -b*10;
			//printf ("i=%d a=%d b=%d c=%d\n", i, a, b, c);
			if (i == (a*a*a + b*b*b + c*c*c)) printf("%d\n",i);
		}
	return 0;
}


fopen:

#include<stdio.h>
int main()
{
	int i, a, b, c;
	//freopen("xt2-2.in", "r", stdin);
	//freopen("xt2-2.out", "w", stdout);
	FILE *fout;
	fout = fopen("xt2-2.out", "wb");
	for (i = 100; i <= 999; i++)
		{
			a = i/100;
			b = i/10 - a*10;
			c = i - a*100 -b*10;
			//printf ("i=%d a=%d b=%d c=%d\n", i, a, b, c);
			if (i == (a*a*a + b*b*b + c*c*c)) fprintf(fout,"%d\r\n",i);
		}

	fclose(fout);
	return 0;
}



习题2-3 韩信点兵

相传韩信才智过人,从不直接清点自己军队的人数,只要让士兵先后以三人一排、五人一排、七人一排地变换队形,而他每次只掠一眼队伍的排尾就知道总人数了。输入3个非负整数a,b,c,表示每种队形排尾的人数(a<3,b<5,c<7),输出总人数的最小值(或报告无解)。已知总人数不小于10,不超过100.

样例输入:2 1 6

样例输出:4 1

样例输入:2 1 3

样例输出:No answer

重定向:

#include<stdio.h>
int main()
{
	int i, a, b, c, d, m;
	freopen("xt2-3.in", "r", stdin);
	freopen("xt2-3.out", "w", stdout);
	while (scanf("%d%d%d", &a, &b, &c) == 3)
	{
		m = 0;
		//d = scanf("%d%d%d", &a, &b, &c);
		//printf("a=%d b=%d c=%d d=%d\n", a, b, c, d);
		for ( i = 10; i<= 100; i++)
			if ((i%3==a)&&(i%5==b)&&(i%7==c))
				{
					m = i;
					printf("%d\n",m);
				}
		if (m == 0) printf("No answer\n");
	}
	//printf("a=%d b=%d c=%d\n", a, b, c);
	return 0;
}


fopen:

#include<stdio.h>
int main()
{
	FILE *fin, *fout;
	int i, a, b, c, d, m;
	//freopen("xt2-3.in", "r", stdin);
	//freopen("xt2-3.out", "w", stdout);
	fin = fopen("xt2-3.in", "rb");
	fout = fopen("xt2-3.out", "wb");
	while (fscanf(fin,"%d%d%d", &a, &b, &c) == 3)
	{
		m = 0;
		//d = scanf("%d%d%d", &a, &b, &c);
		//printf("a=%d b=%d c=%d d=%d\n", a, b, c, d);
		for ( i = 10; i<= 100; i++)
			if ((i%3==a)&&(i%5==b)&&(i%7==c))
				{
					m = i;
					fprintf(fout,"%d\r\n",m);
				}
		if (m == 0) fprintf(fout,"No answer\r\n");
	}
	//printf("a=%d b=%d c=%d\n", a, b, c);
	fclose(fin);
	fclose(fout);
	return 0;
}



习题2-4 倒三角形

输入正整数n<=20,输出一个n层的倒三角形。例如n=5时输出如下:

#########

 #######

  #####

   ###

    #

重定向:

#include<stdio.h>
int main()
{
	freopen("xt2-4.in", "r", stdin);
	freopen("xt2-4.out", "w", stdout);
	int i, j, n;
	while (scanf("%d", &n) == 1)
	{
		for (i=n; i>=1; i--)
			{
				for (j=n-i; j>0; j--) printf(" ");
				for (j=i*2-1; j>= 1; j--) printf("#");
				printf("\r\n");
				
			}

	}
	return 0;
}


fopen:

#include<stdio.h>
int main()
{
	FILE *fin,*fout;
	//freopen("xt2-4.in", "r", stdin);
	//freopen("xt2-4.out", "w", stdout);
	fin = fopen("xt2-4.in", "rb");
	fout = fopen("xt2-4.out", "wb");
	int i, j, n;
	while (fscanf(fin,"%d", &n) == 1)
	{
		for (i=n; i>=1; i--)
			{
				for (j=n-i; j>0; j--) fprintf(fout," ");
				for (j=i*2-1; j>= 1; j--) fprintf(fout,"#");
				fprintf(fout,"\r\n");
				
			}

	}
	fclose(fin);
	fclose(fout);
	return 0;
}




习题2-5 统计

输入一个正整数n,然后读取n个正整数a1,a2,...,an,最后再读一个正整数m。统计a1,a2,...,an中有多少个整数的值小于m。提示:如果重定向和fopen都可以用,哪个比较方便?

重定向:

#include<stdio.h>
int main()
{
	int i,j=1,n,m=0,temp,less = 0;
	freopen("xt2-5.in", "r", stdin);
	freopen("xt2-5.out", "w", stdout);
	scanf("%d", &n);
	for ( i=0; i<=n; i++)
		{
			scanf("%d", &temp);
			if(i==n) m=temp;
			//printf("temp=%d m=%d n=%d i=%d\n",temp,m,n,i);
		}
	freopen("xt2-5.in", "r", stdin);
	scanf("%d", &n);
	while ((scanf("%d", &temp) ==1)&&(j<=n))
		{
		j++;
		//printf("temp=%d m=%d n=%d j=%d\n",temp,m,n,j);
		if(temp<m) less++;
		}
	printf("%d\n",less);
	return 0;
}

fopen:

#include<stdio.h>
int main()
{
	FILE *fin,*fout;
	fin = fopen("xt2-5.in", "rb");
	fout = fopen("xt2-5.out", "wb");
	int i,j=1,n,m=0,temp,less = 0;
	//freopen("xt2-5.in", "r", stdin);
	//freopen("xt2-5.out", "w", stdout);
	fscanf(fin,"%d", &n);
	for ( i=0; i<=n; i++)
		{
			fscanf(fin,"%d", &temp);
			if(i==n) m=temp;
			//fprintf(fout,"temp=%d m=%d n=%d i=%d\r\n",temp,m,n,i);
		}
	fclose(fin);
	fin = fopen("xt2-5.in", "rb");
	//freopen("xt2-5.in", "r", stdin);
	fscanf(fin,"%d", &n);
	while ((fscanf(fin,"%d", &temp) ==1)&&(j<=n))
		{
		j++;
		//fprintf(fout,"temp=%d m=%d n=%d j=%d\r\n",temp,m,n,j);
		if(temp<m) less++;
		}
	fprintf(fout,"%d\r\n",less);
	fclose(fin);
	fclose(fout);
	return 0;
}

习题2-6

输入正整数n,输出H(n)=1+1/2+1/3+...+1/n的值,保留3位小数。例如n=3时答案为1.833。

重定向:

#include<stdio.h>
int main()
{
	int n, j;
	double k,h=0.0;
	freopen("xt2-6.in", "r", stdin);
	freopen("xt2-6.out", "w", stdout);
	while (scanf("%d",&n)==1)
		{
			h=0;
			for (j=1;j<=n;j++)
			{
				k = j;
				h +=1/k;
			//printf("h=%.3lf k=%lf n=%d\n", h,k,n);
			}
			printf("%d %.3lf\n", n,h);
		}
	
}

fopen:

#include<stdio.h>
int main()
{
	int n, j;
	double k,h=0.0;
	FILE *fin, *fout;
	fin = fopen("xt2-6.in", "rb");
	fout = fopen("xt2-6.out", "wb");
	while (fscanf(fin,"%d",&n)==1)
		{
			h=0;
			for (j=1;j<=n;j++)
			{
				k = j;
				h +=1/k;
			//printf("h=%.3lf k=%lf n=%d\n", h,k,n);
			}
			fprintf(fout,"%d %.3lf\r\n", n,h);
		}
	return 0;
}



习题2-7近似计算

计算π/4=1-1/3+1/5-1/7...,直到最后一项小于10的负6次方

重定向:

#include<stdio.h>
int main()
{
	int j;
	double k,h=0.0;
	freopen("xt2-7.out", "w", stdout);
	
			h=0;
			for (j=1;j<=500000;j++)
			{
				k = 2*j-1;
				if (j%2==0) h -=1/k;
					else h +=1/k;
			//printf("h=%lf k=%lf\n", h,k);
			}
			printf("%d\n", h);
	
	
}

fopen:

#include<stdio.h>
int main()
{
	int j;
	double k,h=0.0;
	FILE *fout;
	fout = fopen("xt2-7.out", "wb");
	
			h=0;
			for (j=1;j<=500000;j++)
			{
				k = 2*j-1;
				if (j%2==0) h -=1/k;
					else h +=1/k;
			//printf("h=%lf k=%lf\n", h,k);
			}
			fprintf(fout,"%lf\r\n", h);
	fclose(fout);
	return 0;
}



习题2-8子序列的和

输入两个正整数n<m<10^6,输出1/n*n + 1/(n+1)*(n+1)+...+1/m*m,保留5位小数。例如n=2,m=4时的答案是0.42361;n=65536,m=655360时答案为0.00001。注意:本题有陷阱

重定向:

#include<stdio.h>
int main()
{
	int i,n,m;
	double o,p;
	freopen("xt2-8.in", "r", stdin);
	freopen("xt2-8.out", "w", stdout);
	while(scanf("%d%d",&n,&m)==2)
	{
		p=0;
		for (i=n;i<=m;i++)
		{
			o=i;
			p+=1/(o*o);
			//printf("i=%d n=%d m=%d o=%.5lf p=%.5lf\n", i,n,m,o,p);
		}
		printf("%.5lf\n", p);
	}
	
	
	
}


fopen:

#include<stdio.h>
int main()
{
	int i,n,m;
	double o,p;
	FILE *fin, *fout;
	fin = fopen("xt2-8.in", "rb");
	fout = fopen("xt2-8.out", "wb");
	while(fscanf(fin,"%d%d",&n,&m)==2)
	{
		p=0;
		for (i=n;i<=m;i++)
		{
			o=i;
			p+=1/(o*o);
			//printf("i=%d n=%d m=%d o=%.5lf p=%.5lf\n", i,n,m,o,p);
		}
		fprintf(fout,"%.5lf\r\n", p);
	}
	fclose(fin);
	fclose(fout);
	return 0;
	
}



习题2-9分数化小数

输入正整数a,b,c,输出a/b的小数形式,精确到小数点后c位。a,b<=10^6,c<=100(请注意c=100时可是要求100位精度!)。例如 a=1,b=6,c=4时应输出0.1667.

重定向:

#include<stdio.h>
int main()
{
	int a,b,c,i,wei,yu=0;
	freopen("xt2-9.in", "r", stdin);
	freopen("xt2-9.out", "w", stdout);
	while (scanf("%d%d%d", &a,&b,&c)==3)
	{
		yu=a%b;
		printf("%d.",a/b);
		for (i=1;i<=c;i++)
			{
				if ((i<c)&&(c!=1))
					{
						printf("%d",(yu*10)/b);
					}
				else
					{
						if ((yu*10/b)<5) printf("%d\n",(yu*10)/b);
							else printf("%d\n",((yu*10)/b)+1);
					}
				yu=yu*10%b;
			}
	}
	return 0;
}

fopen:

#include<stdio.h>
int main()
{
	int a,b,c,i,wei,yu=0;
	FILE *fin, *fout;
	fin = fopen("xt2-9.in", "rb");
	fout = fopen("xt2-9.out", "wb");
	while (fscanf(fin,"%d%d%d", &a,&b,&c)==3)
	{
		yu=a%b;
		fprintf(fout,"%d.",a/b);
		for (i=1;i<=c;i++)
			{
				if ((i<c)&&(c!=1))
					{
						fprintf(fout,"%d",(yu*10)/b);
					}
				else
					{
						if ((yu*10/b)<5) fprintf(fout,"%d\r\n",(yu*10)/b);
							else fprintf(fout,"%d\r\n",((yu*10)/b)+1);
					}
				yu=yu*10%b;
			}
	}
	fclose(fin);
	fclose(fout);
	return 0;
}



习题2-10排列

用1,2,3,……,9组成3个三位数abc,def和ghi,每个数字恰好使用一次,要求abc:def:ghi=1:2:3.输出所有解。提示:不必太动脑筋。

重定向:

#include<stdio.h>
int main()
{
	int i;
	freopen("xt2-10.out", "w", stdout);
	for (i=123; i<=333; i++)
		{
			if (((i%10)!=(i/10%10))
				&&((i/10%10)!=(i/100%10))
				&&((i%10)!=(i/100%10))
				&&((i%10)*(i/10%10)*(i/100%10)*
					(2*i%10)*(2*i/10%10)*(2*i/100%10)*
					(3*i%10)*(3*i/10%10)*(3*i/100%10)
					==362880)) printf("%d%d%d\n", i,i*2,i*3);
		}
	return 0;
}

fopen:

#include<stdio.h>
int main()
{
	int i;
	FILE *fout;
	fout = fopen("xt2-10.out", "wb");
	for (i=123; i<=333; i++)
		{
			if (((i%10)!=(i/10%10))
				&&((i/10%10)!=(i/100%10))
				&&((i%10)!=(i/100%10))
				&&((i%10)*(i/10%10)*(i/100%10)*
					(2*i%10)*(2*i/10%10)*(2*i/100%10)*
					(3*i%10)*(3*i/10%10)*(3*i/100%10)
					==362880)) fprintf(fout,"%d%d%d\r\n", i,i*2,i*3);
		}
		fclose(fout);
	return 0;
}



评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值