第二章总结及习题

1.阶乘之和

#include
int main()
{
int n,S,i,j=0;
scanf("%d",&n);
for(i=1;i<=n;i++) //每用一层for循环,及时加一个括号
{
int a=1;
for(j=1;j<=i;j++)
{a=a*j;}
S=S+a;
}
printf("%d\n",S%1000000);
return 0;
}

注意语法书写的规范性

2.水仙花数

1000个数,用暴力搜索

暴力搜索即穷举法,在问题规模不大的时候适用

#include
int main()
{
	int n,a,b,c;
	for(n=100;n<1000;n++)    //穷举数字
	{
		a=n/100;
		b=n/10%10;
		c=n%10;      //个位数字的提取
		if(n==a*a*a+b*b*b+c*c*c)
		printf("%d\n",n);
	}
	return 0;
}

结果:153,370,371,407

3.韩信点兵

(法1)暴力搜索求解

#include
int main()
{
	int a,b,c,n,count=0;
	while(scanf("%d%d%d",&a,&b,&c)!=EOF)//  将输入的返回值个数作为返回条件,可以得到多组输入值 
	{
      for(n=10;n<=100;n++)
	  { 
	    if(n%3==a&&n%5==b&&n%7==c)
	    {
	    count++;
     	printf("Case %d:%d\n",count,n);
    	break;
	    }
	  }
     if(n>100)
     printf("Case %d:No answer\n",++count);
    }
    return 0;
}

注意:
这个题目中用到了scanf()。将其放在while循环语句的条件部分,可以用于判断循环的输入是否结束。
1.while(scanf("%d",&a)==1)
该语句用于判断单组多个数值的输入(如例题“最大值最小值平均值”),当需要停止时记得按ctrl+z
2.while(scanf(“%d”,&a)!=EOF)
该语句用于判断多组数值输入。

EOF为是一个计算机术语,为End Of File的缩写,在操作系统中表示资料源无更多的资料可读取。资料源通常称为档案或串流。通常在文本的最后存在此字符表示资料结束。C语言中,EOF常被作为文件结束的标志。还有很多文件处理函数处错误后的返回值也是EOF,因此常被用来判断调用一个函数是否成功。
[https://blog.csdn.net/qq_37909508/article/details/79498051]

scanf("%d%d", &x, &y):
如果x和y能够被成功读入,那么scanf的返回值就是2
如果只有a被成功读入,返回值为1
如果a和b都未被成功读入,返回值为0
如果遇到错误或遇到end of file,返回值为EOF

(法2)“中国剩余定理求解”

 #include 
    int main (void)
    {
        int a,b,c,count=0;
        while(scanf("%d%d%d",&a,&b,&c)!=EOF)
        {
        	int sum;
        	sum=a*70+b*21+c*15;//中国剩余定理,注意a乘70
        	if(sum%105<=100)
    		printf("Case %d:%d\n",++count,sum%105); 
    	    else
    	    printf("Case %d:No answer\n",++count);
    	}
        return 0;
    }

韩信点兵是一个有趣的猜数游戏。如果你随便拿一把蚕豆(数目约在100粒左右),先3粒3粒地数,直到不满3粒时,把余数记下来;第二次再5粒5粒地数,最后把余数记下来;第三次是7粒一数,把余数记下来。然后根据每次的余数,就可以知道你原来拿了多少粒蚕豆了。不信的话,你还可以试验一下。例如,假如3粒一数余1粒,5粒一数余2粒,7粒一数余2粒,那么,原有蚕豆有多少粒呢?
这类题目看起来是很难计算的,可是我国古时候却流传着一种算法,名称也很多,宋朝周密叫它“鬼谷算”,又名“隔墙算”;杨辉叫它“剪管术”;而比较通行的名称是“韩信点兵”。最初记述这类算法的是一本名叫《孙子算经》的书,后来在宋朝经过数学家秦九韶的推广,又发现了一种算法,叫做“大衍求一术”。这在数学史上是极有名的问题,外国人一般把它称为“中国剩余定理”。
方法:
它的意思是:凡是用3个一数剩下的余数,将它用70去乘(因为70是5与7的倍数,而又是以3去除余1的数);5个一数剩下的余数,将它用21去乘(因为21是3与7的倍数,又是以5去除余1的数);7个一数剩下的余数,将它用15去乘(因为15是3与5的倍数,又是以7去除余1的数),将这些数加起来,若超过105,就减掉105,如果剩下来的数目还是比105大,就再减去105,直到得数比105小为止。这样,所得的数就是原来的数了。
“中国剩余定理”资料页

4.倒三角形

找到三角形中字符与行数,空格与行数之间的规律是关键

#include
int main()
{
	int n,m,i;//n为总层数,m为行数,i为个数 
	scanf("%d",&n);
	if(n<=20)
	{
		for(m=0;m

5.正三角形

同倒三角形原理

注意:
1.一定要在编程前,分清楚总行数n,行数m,个数i(包括空格和元素)
2.分清楚是从1开始计数还是从0开始计数。从0开始的话,凡是涉及到总行数n的要减去1

#include
int main()
{
	int n,m,i;//n为总层数,m为行数,i为个数 
	scanf("%d",&n);
	if(n<=20)
	{
		for(m=1;m<=n;m++)//根据输入的行数,依次遍历每一行,m为行数 
		{
			for(i=1;i<=n-m;i++)//根据总层数n,找到每一m行中“空格”元素的个数 。为n-m 
			{
				printf(" ");
			}
			for(i=1;i<=2*m-1;i++)//根据总层数n,找到每一m行中“#”元素的个数。为 2*m-1
			{
				printf("#");
			}
			printf("\n");
		}
	}
	return 0;
}

6.子序列的和

注意:
题中有陷阱,即要用long long int类型(int只能表示10^6);另外,注意变量的作用域(sum用于局部变量,且为0.0);再者要注意强制格式转换

#include
int main()
{
	long long n,m,i;
	int count=0;
	while(scanf("%lld %lld",&n,&m)==2&&(n!=0&&m!=0))
	{
		double sum=0.0;//sum要放在循环中,作为局部变量,否则会出错。所以变量定义时的范围要注意 
		for(i=n;i<=m;i++)
		{
			sum+=1.0/(double)(i*i);//用double进行强制格式转换
		}
	 printf("Case %d:%.5f",++count,sum);
	 } 
    return 0;
}

7.分数化小数

注意:

1.三个0标记结束的表示方法

while(scanf("%d %d %d",&a,&b,&c) == 3 && ! (a == 0&&b == 0&&c == 0))//表示三个数均为0时退出

有人写成

while(scanf("%d %d %d",&a,&b,&c)==3 &&a&&b&&c)

是不对的,这个代表有一个为0即退出
2.如何得到带小数除法,而不是得到整数部分:a和b均加上0.0
3.如何做到精确c位(根据输入改变)

printf("%.*f",c,(double)(a+0.0)/(b+0.0)); 

*代表取一个int型参数,并把它作为精度
代码

#include 
int main (void)
{
	int a,b,c;
    while(scanf("%d %d %d",&a,&b,&c)==3 && !(a==0&&b==0&&c==0))
    {
		printf("%.*f",c,(double)(a+0.0)/(b+0.0));//%.*f中的*表示读取一个int型参数,并把它作为精度 
	} 
    return 0;
}

8.四舍五入可控制输入

平时在四舍五入时会用%.f的形式控制格式,这种情况无法根据输入控制。
可控的原理:当一个数要保留n位时,我们可以先将其乘上10的n次方在加(减)去0.5,然后除以10的n次方(后面的.0不能省略,因为这保证了最后运算出来的是个小数)。(正数加,负数减)
涉及一个新的函数pow() 用来求 x 的 y 次幂(即x^y),x、y及函数值都是double型 ,其原型为:double pow(double x, double y);
代码

#include 
#include 
int main()
{
	double a,b,c;
	double bit;
	printf("请输入你想要四舍五入的小数\n");
	scanf("%lf",&a);
	printf("请输入精确的位数\n");
	scanf("%lf",&bit);
	if (a > 0)
	{
		b=pow(10,bit);
		c=(a*b+0.5)/b;
		}
	else if(a<0)
	{
		b=pow(10,bit);
		c=(a*b-0.5)/b;
		}	
	printf("%.*lf\n",(int)bit,c);	//精度控制处的*代表读取一个int型参数并把它当做精度,即读取bit
	return 0;
}

加入可输入输出多组数值的机制

#include 
#include 
int main()
{
	double a,b,c;
	double bit;
	printf("请输入四舍五入的小数和精确到的位数");
	while(scanf("%lf %lf",&a,&bit)!=EOF)
	{
		if (a > 0)
	{
		b=pow(10,bit);
		c=(a*b+0.5)/b;
		}
	else if(a<0)
	{
		b=pow(10,bit);
		c=(a*b-0.5)/b;
		}	
	printf("%.*lf\n",(int)bit,c);	//精度控制处的*代表读取一个int型参数并把它当做精度,即读取bit
	}
	return 0;
}

你可能感兴趣的:(算法竞赛入门-第二章练习)