SDUT-程序设计基础-实验4-for循环(下)
在开始之前,我想要提醒一下大家,在看完答案和解析以后,一定要自己再写一遍,一味的复制粘贴没有任何效果,当然,再解析中有任何看不懂的内容都可以私信我!!
这期的难度远高于上一期,请大家认真理解,真的自己打一遍
15.sdut-C语言实验-完美的素数
题干如下
素数又称质数。指一个大于1的自然数,除了1和此整数自身外,不能被其他自然数整除的数。我们定义:如果一个素数是完美的素数,当且仅当它的每一位数字之和也是一个素数。现在给你一个正整数,你需要写个程序判断一下这个数按照上面的定义是不是一个完美的素数。
输入格式:
输入包含多组测试数据。
每组测试数据只包含一个正整数 n (1 < n <= 10^6)。
输出格式:
对于每组测试数据,如果 n 是完美的素数,输出“YES”,否则输出“NO”(输出均不含引号)。
输入样例:
在这里给出一组输入。例如:
11
13
输出样例:
在这里给出相应的输出。例如:
YES
NO
这个题目,需要我们深刻理解上面第九题的做题思路,需要用到枚举的方法,这里不多说,根据题干的意思,这只是一个条件,同时需要分割输入的数,这个不难,然后加和为原数,才可被称为完美素数,所以我们只需要将两个分开判断,只要同时满足就输出yes反而输出no
#include<stdio.h>
int get_prime (int a)
{
int i = 0;
for (i = a - 1; i > 1; i--)
{
if (a % i == 0)
{
return 0;
}
}
if (i == 1)
return 1;
}
int main()
{
int n, a, sum, m, b;
while(scanf("%d",&n) != EOF)
{
a = get_prime(n);
sum = 0;
while(n>0)
{
m = n % 10;
sum += m;
n /= 10;
}
b = get_prime(sum);
if(a == 1&&b == 1)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
16.sdut-C语言实验-余弦
题干如下
输入n的值,计算cos(x)。
输入格式:
输入数据有多行,每行两个数,包括x和n。第一数据为x,第二个数据为n。
输出格式:
输出cos(x)的值,保留4位小数。
输入样例:
在这里给出一组输入。例如:
0.0 100
1.5 3
输出样例:
在这里给出相应的输出。例如:
1.0000
0.0701
这个题目给出两个不同的方法
1.递推的方法,即后一项=前一项XX / ((2i)(2*i-1)),这个是这个题目相对简单的一种方式,也较为难理解,但可以减少代码长度,更加精简,不做赘述
#include <stdio.h>
int main()
{
double x;
int n;
while(scanf("%lf %d", &x, &n) != EOF)
{
double k = 1.0, flag = 1.0, ans = 0.0;
for(int i = 0; i <= n; i ++)
{
if(i != 0)
{
k = k*(x*x)*1.0/((2*i)*(2*i-1));
}
ans += (k*flag);
flag = -flag;
}
printf("%.4lf\n", ans);
}
return 0;
}
2.这个方法就是通项,这个相对好理解,但写起来不算简单,根据题干的意思列出通项,然后加和即可完成,在此过程中需要用到循环的嵌套,同时需要用到pow这个函数,用法
例 pow(a,b)即求a的b次方,当然也要引用math这个头函数,只要思路清晰,循环套循环并没有想象中那么难。
#include<stdio.h>
#include<math.h>
int main()
{
int n,i,j;
double x,s,a;
while(scanf("%lf%d",&x,&n)!=EOF)
{
s=1;
for(i=1;i<=n;i++)
{
a=1;
for(j=1;j<=2*i;j++)
{
a*=j;
}
s=s+pow(-1,i)*pow(x,2*i)/a;
}
printf("%.4lf\n",s);
}
return 0;
}
17.sdut-C语言实验-求某个范围内的所有素数
题干如下
求小于n的所有素数,按照每行10个显示出来。
输入格式:
输入整数n(n<10000)。
输出格式:
每行10个依次输出n以内(不包括n)的所有素数。如果一行有10个素数,每个素数后面都有一个空格,包括每行最后一个素数。
输入样例:
100
输出样例:
2 3 5 7 11 13 17 19 23 29
31 37 41 43 47 53 59 61 67 71
73 79 83 89 97
对于这个题目,也需要之前题目的铺垫,只要判断素数的枚举能理解,这个题目只需要多一个判断条件,即使用一个变量不断累加,在取余10得整数,即10的倍数的时候,换行即可实现题目要求
#include <stdio.h>
int main()
{
int n,a=0,i,t;
scanf("%d",&n);
for(i=2;i<n;i++)
{
if(i==2)
{
printf("%d ",i);
a++;
}
else
{
for(t=2;t<i;t++)
{
if(i%t==0)
break;
}
if(i==t)
{
printf("%d ",i);
a++;
if(a%10==0)
printf("\n");
}
}
}
return 0;
}
18.水仙花数
题干如下
水仙花数是指一个N位正整数(N≥3),它的每个位上的数字的N次幂之和等于它本身,本题要求编写程序,计算所有N位水仙花数。
输入格式:
输入在一行中给出一个正整数N(3≤N≤7)。
输出格式:
按递增顺序输出所有N位水仙花数,每个数字占一行。
输入样例:
3
输出样例:
153
370
371
407
这个题目难度相对较高,首先我们需要明白,怎么实现范围的固定,即确定为N位数,这里需要用到pow这个函数,用法见上题,只需要控制范围在pow(10,N-1)<=
x < pow(10,
N),这个很好理解,10的一次方是2位数,且最后一个是100-1,这样就可以做到范围的控制,然后后面就是常规的,维护循环中的几个变量,实现不断加和,最后进行判断然后打印即可
#include<stdio.h>
int pow(int m,int n) //定义函数速度大于调用库函数
{
int j, s = 1;
for (j = 1; j <= n; j++)
{
s *= m;
}
return s;
}//这里可以直接引用math头函数,就无需写这个函数了
int main()
{
int n, m;
scanf("%d", &n);
int x = 0;
for (x = pow(10, n - 1); x < (pow(10, n)); x++)
{
int b = x; //保存x的值
int sum = 0, a = 0, i;
for (i = 1; i <= n; i++)
{
a = b % 10; //a是x的最后一位
b /= 10; //b不段除10去掉后一位
sum += pow(a, n);
}
if (sum == x)
{
printf("%d\n", x);
}
}
return 0;
}
19.计算阶乘和
题干如下
对于给定的正整数N,需要你计算 S=1!+2!+3!+…+N!。
输入格式:
输入在一行中给出一个不超过10的正整数N。
输出格式:
在一行中输出S的值。
输入样例:
3
输出样例:
9
这个题目给出两种不同的方法
1.常规方法,我们只需要根据题干的意思,维护变量,然后加和,同时这里的阶乘给出一种递推的方法,即前一个数的阶乘再乘下个数就是下个数的阶乘,实现了对循环结构的优化,当然也可以再嵌套一个循环,求出每个数的阶乘和。
#include <stdio.h>
int main ()
{
int factorial=1, sum=0, n, i;
scanf ("%d",&n);
for ( i=1; i<=n; i++)
{
factorial *= i;
sum += factorial;
}
printf("%d",sum);
return 0 ;
}
2.函数的做法,即如果没想到递推的方法时,可以实现对循环结构的优化,可以防止循环的嵌套,减少难度
#include<stdio.h>
int get_factorial (int m)
{
int i = 1, sum = 1;
for(i;i<=m;i++)
{
sum *= i;
}
return sum;
}
int main()
{
int a,sum=0,t;
scanf("%d",&a);
for(int i = 1 ; i <= a ; i++)
{
t = get_factorial(i);
sum += t;
}
printf("%d",sum);
return 0;
}
20.输出整数各位数字
本题要求编写程序,对输入的一个整数,从高位开始逐位分割并输出它的各位数字。
输入格式:
输入在一行中给出一个长整型范围内的非负整数。
输出格式:
从高位开始逐位输出该整数的各位数字,每个数字后面有一个空格。
输入样例:
123456
输出样例:
1 2 3 4 5 6
这个题目给出两种不同的方法
1.第一种方法是函数递归,递归可以理解成为函数的嵌套,即在函数中再次引用这个函数,属于较难理解的方法,可以暂时初步接触一下,理解即可,不要求写出来
#include<stdio.h>
void get_print (long long m)
{
if(m > 9)
get_print(m / 10);
printf("%d ", m % 10);
}
int main()
{
long long a;
scanf("%lld", &a);
get_print(a);
return 0;
}
2.第二种即为循环中拆分数字的做法,是一种常见的方法,这里不做赘述
#include<stdio.h>
int main(){
int n, t;
int m=1;
scanf("%d", &n);
t = n;
while(t/10 != 0)
{
m *= 10;
t /= 10;
}
while(m!=0)
{
printf("%d ", n/m);
n %= m;
m /= 10;
}
return 0;
}
21.打印九九口诀表
题干如下
下面是一个完整的下三角九九口诀表:
11=1
12=2 22=4
13=3 23=6 33=9
14=4 24=8 34=12 44=16
15=5 25=10 35=15 45=20 55=25
16=6 26=12 36=18 46=24 56=30 66=36
17=7 27=14 37=21 47=28 57=35 67=42 77=49
18=8 28=16 38=24 48=32 58=40 68=48 78=56 88=64
19=9 29=18 39=27 49=36 59=45 69=54 79=63 89=72 99=81
本题要求对任意给定的一位正整数N,输出从11到N*N的部分口诀表。
输入格式:
输入在一行中给出一个正整数N(1≤N≤9)。
输出格式:
输出下三角N*N部分口诀表,其中等号右边数字占4位、左对齐。
输入样例:
4
输出样例:
11=1
12=2 22=4
13=3 23=6 33=9
14=4 24=8 34=12 44=16
对于这个题目,相较于之前的题目,没有什么难点,唯一的难点在于如何占四位,左对齐,一般来说,我们会使用 %nd
的方式来保留占n位,但此时,默认是右对齐,因此,只需要在n前面加上一个负号就可以实现左对齐,然后是要注意给换行设定一个判断条件,来实现打印九九乘法表
#include<stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
int i = 0, j = 0;
for(i = 1 ; i <= n ; i ++)
{
for(j = 1 ; j <= i ; j ++)
{
printf("%d*%d=%-4d", j, i, i*j);
}
printf("\n");
}
return 0;
}
22.找完数
题干如下
所谓完数就是该数恰好等于除自身外的因子之和。例如:6=1+2+3,其中1、2、3为6的因子。本题要求编写程序,找出任意两正整数m和n之间的所有完数。
输入格式:
输入在一行中给出2个正整数m和n(1< m ≤ n ≤ 10000),中间以空格分隔。
输出格式:
逐行输出给定范围内每个完数的因子累加形式的分解式,每个完数占一行,格式为“完数 = 因子1 + 因子2 + … + 因子k”,其中完数和因子均按递增顺序给出。若区间内没有完数,则输出“None”。
输入样例:
2 30
输出样例:
6 = 1 + 2 + 3
28 = 1 + 2 + 4 + 7 + 14
对于这个题目,在做之前需要大家理清思路,思路不清晰容易越做越乱,首先,我们需要确定,什么是完数,根据题干的意思就是把所有因数相加,显然,这里需要一个循环,其次,要根据第一行给出的数字判断范围,要使用枚举法,这里也是一个循环,并且这个循环是需要套在上个循环之外的,再其次,这里需要一个判断条件查看是否存在完数,最后就是如何打印,在打印的时候,肯定是先寻找因数,因此这也是一个循环,写到这里,这个题目就迎刃而解了。
#include<stdio.h>
int get_perfect(int a)//此函数可以放在主函数内
{
int sum = 0, i;
for (i = 1; i < a; i++)
{
if (a % i == 0)
{
sum += i;
}
}
if (sum == a)
return 1;
return 0;
}
int main()
{
int a, b, c, count = 0;
scanf("%d %d", &a, &b);
for (int i = a; i <= b; i++)//一重循环
{
c = get_perfect(i);
if (c == 1)
{
count++;//判断条件
printf("%d = 1", i);
for (int j = 2; j < i; j++)//内循环
{
if (i % j == 0)
{
printf(" + %d", j);
}
if (j == i - 1)
printf("\n");
}
}
}
if (count == 0)
printf("None");
return 0;
}
23.编程打印空心字符菱形
题干如下
本题目要求读入菱形起始字母和菱形的高度,然后输出空心字符菱形。所谓“空心菱形”是指:每行由两端为字母、中间为空格的字符串构成,每行的字符串中心对齐;上半部分相邻两行字符串长度差2,且字母从给定的起始字母逐一递增;下半部分与上半部分对称。
输入格式:
输入在一行中给出起始字母(范围为英文大写字母A-G)和菱形的高度(为不超过10的奇数)。
输出格式:
输出空心字符菱形。
输入样例:
B 5
输出样例:
B
C C
D D
C C
B
这个题目是整个实验四当中最难的一部分,后续我会专门出一个关于如何打印各种菱形的博客(指挖坑不知道什么时候填),大家记得及时观察动态。这个题目的详细解析放到代码中了。
#include <stdio.h>
// 1、先画出实心菱形(把菱形分成上下俩部分,再分成正三角和倒三角 )
// 2、 把输入的N(n层)带入循环
// 3、 用if语句使菱形中心为空
// 4、 利用ASCII码的加减 实现字母组成
int main()
{
int n,i,j;
char c;
scanf("%c%d",&c,&n);
//针对奇数层的菱形 上部分
for(i=1;i<=n/2+1;i++)
{
//第一个为上班边的倒三角
for(j=n/2;j>=i;j--)
printf(" ");
//第二个上半边的正三角
for(j=0;j<i*2-1;j++)
{
//菱形中间的空心用if else来实现
if(j==0 || j==i*2-2)
printf("%c",c);
else
printf(" ");
}
c+=1;
printf("\n");
}
c-=1;
//下部分
for(i=1;i<=n/2;i++)
{
c-=1;
//第三个为下半边的正三角
for(j=1;j<=i;j++)
printf(" ");
//第四个三角形为倒三角形
for(j=n-2;j>=i*2-1;j--)
{
if(j==n-2 || j==i*2-1)
printf("%c",c);
else
printf(" ");
}
printf("\n");
}
}
24.求数列前n项之和
题干如下
已知数列1,1/3,1/5,1/7,…,求出其前n项之和,其中的实型变量用double类型。
输入格式:
输入n的值,n的值为1到100之间的整数。
输出格式:
以保留两位小数的形式输出数列前n项的和并换行。
输入样例:
3
输出样例:
1.53
这个题目较为简单,相信不会难倒大家,只需要维护分母和加和两个变量即可,并不难。
#include<stdio.h>
int main()
{
int n, m;
double a,sum=0.0;
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
m = 2 * i + 1;
a = 1.0/m;
sum += a;
}
printf("%.2lf\n",sum);
return 0;
}