感觉c实验课强度开始上来了
【id:404】【20分】A. 输出三角形字符阵列
这一题难点在于如何表达字符ABCD……
#include <stdio.h>
int main() {
int N;
scanf("%d", &N);
for (int a = N, add = 0; a > 0; a--) { /* add为ASCII码增加值 */
for (int n = 1; n <= a; n++, add++) { /* 定义步长n,每次执行n=a次循环 */
printf("%c ", 'A' + add);
}
printf("\n");
}
return 0;
}
如代码,A~Z的ascii码值是连续递增的,因此只需要每次在前一次的ascii值上+1即可
救命,原来ascii最后两个是ii不是ll
(American Standard Code for Information Interchange)
【id:478】【20分】B. 求幂级数展开的部分和
#include <stdio.h>
#include <math.h>
double fact(int k) { /* 求k的阶乘 */
double a = 1;
for (; k > 0; k--) {
a = a * k;
}
return a;
}
int main() {
double x, y = 1;
int k = 1;
scanf("%lf", &x);
for (; fabs(1.0 * pow(x, k) / fact(k)) >= 0.00001; k++) { /* 虽然题目要求要加fab但是好像一定是正数其实并不需要他…… */
y = y + 1.0 * pow(x, k) / fact(k);
}
k++;
y = y + 1.0 * pow(x, k) / fact(k); /* 再执行一次 */
printf("%.4lf", y);
return 0;
}
这里开始用到了函数的定义和调用。
为了方便求k的阶乘我在代码的开头定义了一个函数fact()。而后当我需要求某个数的阶乘时就只需要像使用fabs()这些函数一样直接写出来就可以用了。
下面单独拎出我定义的fact()函数谈谈:
#include <stdio.h>
#include <math.h>
/* 求k的阶乘 */
double fact(int k) { /*"double"表示后续要return回主函数的值的类型 */
double a = 1; /* 上面括号中的"int k"代表读入的数的类型是整型 */
for (; k > 0; k--) {
a = a * k;
}
return a; /* 这里返回主函数一个值,返回的类型是开头的"double" */
}
int main() {
int a=3;
a = fact(a); /* 调用前面定义的fact()函数,括号里输入了要运算的数,待函数执行完后会被return回一个值 */
printf("%d", a);
return 0;
}
输出结果为:6
————————
在这道题中要注意的是,for循环一旦条件不满足就不会执行,但是题目要求的是“求和一直继续到最后一项的绝对值小于0.00001”,因此最后的一项依然要加到y中,因此第22,23行单独又执行了一遍相加
下面看看我第一次写的代码:
#include <stdio.h>
#include <math.h>
double fact(int k) { /* 求k的阶乘 */
double a = 1;
for (; k > 0; k--) {
a = a * k;
}
return a;
}
int main() {
double x, y = 1;
int k = 0;
scanf("%lf", &x);
do {
k++;
y = y + 1.0 * pow(x, k) / fact(k);
} while (fabs(1.0 * pow(x, k) / fact(k)) >= 0.00001);
k++;
y = y + 1.0 * pow(x, k) / fact(k); /* 再执行一次 */
printf("%.4lf", y);
return 0;
}
这是一个错误的案例。这个代码与上面代码的差异只是for循环换成了do-while循环,但是造成的结果却大不相同——差异在输入特殊值后得运行上。
do-while循环会先无视条件执行一次循环,这就导致如果我输入的x是一个非常小的数——使得第21行条件pow(x, k) / fact(k) 已经比0.00001还要小了,但是do-while循环会先执行一次,而后面22-23行还会再执行一次,这就使得运算出来的结果多执行了一次求和,导致有一个样例会过不去。
【id:403】【20分】C. 输出整数各位数字
#include <stdio.h>
int main() {
int x, mask = 1;
scanf("%d", &x);
int temp = x; /* temp为临时值 */
/* 计算x为几位数,若两位则mask为10,三位则为100,类推 */
while (temp > 9) {
temp = temp / 10;
mask *= 10;
}
/* 逐一输出 */
for (; mask >= 1; mask /= 10) {
temp = x / mask; /* 从左到右取出数字 */
x = x % mask;
printf("%d ", temp);
}
return 0;
}
因为要正序输出各个位数所以要先计算一共是多少位数,如果是倒序输出则不用那么麻烦。
然后!!差点没写上来!!有个人写了个超简单厉害的!!!(这里特别点名yyx同学咳咳
yyxyyxyyxyyxyyxyyxyyxyyx这次没打错了(哭死
#include <stdio.h>
#include <string.h>
int main() {
char num_str[20];
int i;
scanf("%s", num_str);
for (i = 0; i < strlen(num_str); i++) {
printf("%c ", num_str[i]);
}
return 0;
}
看完她的我感觉我写的要那么多代码好像小丑(哭
【id:34】【20分】D. 判断回文数
与上题相反,这一题的思路是想办法得到倒序的数字(或者可以让中间的数或者中间的位置为跷跷板,比较两边是否镜像)
以下是用倒序比较的写法:
#include <stdio.h>
int main() {
int n, x, y = 0, temp; /* temp为临时值 */
scanf("%d", &n);
for (; n > 0; n--, y = 0) { /* 每次都要重置一次y */ /* 这里用来循环n次 */
scanf("%d", &x);
temp = x; /* 保存x值(下面计算会破坏x值) */
for (; x >= 1; x /= 10) { /* 这里用来倒序x */
y = y * 10 + x % 10; /* 关键计算 */
}
if (temp == y) {
printf("Yes\n");
} else {
printf("No\n");
}
}
return 0;
}
下面是用把数字当成跷跷板比较镜像数字的写法(取自hgx):
#include <stdio.h>
#include <string.h>
int main() {
int n;
scanf("%d", &n);
getchar(); /* 这个用于吃掉输入数字后的换行符,不然第10行gets()会吃进换行符 */
char s[1005];
while (n--) { /* 当n为0时表示条件不满足 */
gets(s);
int flag = 1;
int lenth = strlen(s); /* 保存读入数组长度 */
for (int i = 0; i < lenth; i++) {
if (s[i] != s[lenth - 1 - i]) { /* 将数字前后镜像位数比较 */
flag = 0;
break;
}
}
if (flag != 0) {
printf("Yes\n");
} else {
printf("No\n");
}
}
return 0;
}
上面第13行的镜像比较实际上会多反过来比较一轮(如判断131,先第一位和第三位比较,然后第二位和第二位比较,然后再第三位和第一位比较)。但是考虑到时间复杂度本来就不高所以不需要做优化。
样例中有一项是判断一个个位数是不是回文数(应该输出Yes)。如果你一直卡在第二个样例的话那就是你的代码需要特判个位数。
【id:400】【20分】E. 验证“哥德巴赫猜想”
#include <stdio.h>
#include <math.h>
int fact(int p) { /* 验证是否素数 */
int a = 1;
if (p == 1 || p == 2) { /* 特判1和2 */
return a;
}
for (int n = 2; n <= sqrt(p) + 1; n++) { /* 这里如果不以根号判断会超时 */
if (p % n == 0) {
a = 0;
break;
}
}
return a;
}
int main() {
int N;
scanf("%d", &N);
int n = 2;
for (; n <= N; n++) {
if (fact(n) && fact(N - n)) { /* 验证两数是否都是素数 */
break;
}
}
printf("%d = %d + %d", N, n, N - n);
return 0;
}
自信之作!!
关于N的定义,因为在32位和64位机器中,int占32位,取值范围为-2147483648~2147483647()而2*10^9刚好小于这个最大的正数,所以不需要用double型或者long long型
如果你的答案提交总是报告“超时”,是因为你判断素数的方法还不够优化。如第9行,判断一直到根号p即可,不需要从2-p全部判断一遍。(我一开始这样超时了三四次。。)
剩下要注意的点就是使用sqrt()函数需要引入<math.h>库
关于第23行能运行的原理,需要了解一下c的逻辑判断。在python中有布尔值True和False,而c以1和0分辨。所以当你的if后括号内内容为“1”时会判断为“真”,为“0”时会判断为“假”。