16级程序设计基础实践第一次月考
Begin Time: 2016-10-27 13:00:00
End Time: 2016-10-27 14:45:00
Judge: By File
第一次上机考试,题目不难,但是对于初学者来说确实不是很容易AC,毕竟初学者出现错误以后没有办法快速准确地自己看出问题所在。
我做完以后一直等到考试时间结束,期间看着Submitted数字不断地上升,而Accepted数字几乎不动,直到考试结束前半分钟,我记下了这次考试的数据。
A Lab04_01 39.52%(132/334)
B Lab04_02 7.88%(32/406)
C Lab04_03 8.55%(33/386)
D Lab04_04(选做) 25.71%(18/70)
第一题,最简单。
Problem A:Lab04_01
Time Limit:1000MS Memory Limit:30000KB
Description
输入两个整数,第1行输出这两个数的逻辑或的值;第2行输出这两个数的位或的值;第3行输出这两个数的位异或的值。
Input
输入两个整数
Output
第1行输出这两个数的逻辑或的值;第2行输出这两个数的位或的值;第3行输出这两个数的位异或的值。
Sample Input
1 1
Sample Output
1
1
0
直接给出代码,没有需要注意的地方。
#include <stdio.h> #include <stdlib.h> int main() { int a,b; scanf("%d%d",&a,&b); printf("%d\n",a||b); printf("%d\n",a|b); printf("%d\n",a^b); return 0; }
第二题,也不难。
Problem B:Lab04_02
Time Limit:1000MS Memory Limit:30000KB
Description
输入一个非负int类型整数,在一行中输出该数的二进制表示中值为1的位数,以及最简分数表示的占比(格式分子:方母,如1:16,1:1等),位数与占比之间用一个逗号分隔。
例如:
Input:
3
Output:
2,1:16
Note:
示例数据的输出以某个32位的机器为例
Input
输入一个非负int类型整数
Output
在一行中输出该数的二进制表示中值为1的位数,以及最简分数表示的占比(格式分子:方母,如1:16,1:1等),位数与占比之间用一个逗号分隔。
Sample Input
0
Sample Output
0,0:32
这里直接给出代码。
#include <stdio.h> #include <stdlib.h> int gcd(int a, int b) { if (b==0) { return a; } else { return gcd(b,a%b); } } int main() { unsigned int num; int i=0,count=0,a[100]= {0}; scanf("%ud",&num); while (num>0) { a[i]= num % 2; num = num / 2; i++; } num=i; while (i>=0) { if (a[i]==1) count++; i--; } if (count==0) { printf("%d,%d:%d\n",0,0,32); } else { int div =gcd (count,32); printf("%d,%d:%d\n",count,count/div,32/div); } return 0; }
需要注意的有这么几点:
1、数组a开到了100,有点浪费了。
2、这里的输入数字num采用的是unsigned int。
3、计数的过程与前一篇略有差异,这里采用的是从数组最后一位往前的方法。
4、由于任何数都是0的因数,所以0与32的最大公约数是32,因此需要单独考虑count为0的情形。
5、约分到最简,就是分子分母同时除以最大公约数。
6、输出结果需要有换行符。
7、变量一定要记得初始化,这里都是赋初值0。
第三题,与上次作业题类似,简单。
Problem C:Lab04_03
Time Limit:1000MS Memory Limit:30000KB
Description
统计并输出一段文字中大写字母开头的单词个数。
例如:
Input:
The C
programming language
Output:
2
Note:
在一行中,单词与单词之间用一个或多个空格分隔,每行末尾有一个换行符
Input
输入一段文本
Output
输出文字中大写字母开头的单词个数
Sample Input
This is a exmaple
there are SOME Books
Sample Output
3
直接给出代码。
#include <stdio.h> #include <stdlib.h> int main() { char ch; int isnew=1,count=0; while (scanf("%c",&ch)==1) { if (ch>='A' && ch <='Z') { if (isnew) { count++; isnew=0; } } else { isnew=0; if (ch==' '|| ch=='\n'|| ch=='\t') { isnew=1; } } } printf("%d\n",count); return 0; }
需要注意的有这么几点:
1、因为空格有一个或多个,所以不能单纯地以flag=!flag这种方法来更改逻辑值。
2、判断是否文件结束仍旧采用的是scanf的返回值。
3、
if (ch>='A' && ch <='Z') { //如果这是大写字母 if (isnew) { //判断是不是一个新单词的开头 count++; //如果是,就让计数器加1 isnew=0; //并且把isnew设置为false }
4、在else的部分,有一句isnew=0。这里详细说说这句话的含义。
题目说的很清楚,“大写字母开头的单词”,也就是说大写字母必须在首位才是计数的,例如Apple是计数的,SOME是仅记一次(而不是四次),heLLo是不计数的。
但是事实上,在OJ判断的时候,似乎只考虑了Apple、apple、APPLE这样的情况,并没有考虑到aPPlE这样的情况,所以这句话不写竟然也被OJ认为是通过的。这句话应该是要写的。
else { //否则(也就是不是大写字母) isnew=0; //一个字符不是大写字母//不论是小写字母还是其他的//都认为之后遇到的不是一个新单词//把isnew设置为false//即便是空格,也先这样处理,之后再改 if (ch==' '|| ch=='\n'|| ch=='\t') { isnew=1; //如果是空格,那么之后遇到的就应该是新一个单词了 } }
5、输出最后要有换行符。
第四题,选做题,难度确实最大,但是只要知道牛顿二项式定理,直接写就是了,没有难度。
Problem D:Lab04_04(选做)
Time Limit:1000MS Memory Limit:30000KB
Description
使用Newton-Raphson算法求解方程:2χ3-4χ2+3χ-6=0在1.5附近的根(保留3位小数)。在一行中输出根的值。
本题没有输入,也不提供示例输出。
直接输出答案的,一律判为0分。
Note:
参考曲线
(注:图略)
Input
无
Output
在一行中输出根的值(保留三位小数)。
Sample Input
无
Sample Output
不给
#include <stdio.h> #include <stdlib.h> #include <math.h> double f(double x) { return (2*pow(x,3)-4*pow(x,2)+3*x-6); } //原函数 double f1(double x) { return (6*pow(x,2)-8*x+3); } //导数 int main() { double x=1.5; //从1.5开始试 while (fabs(f(x))>0.00001) { //精度要求 x=(-(f(x)))/(f1(x))+x; //N-R定理 } printf("%0.3f\n",x); //场宽(域宽) return 0; } //特别注意,绝对值是fabs(),不是abs()
正文完。
然后给出某同学的第二题做法。
先给出代码,然后详细说明。
#include<stdio.h> #include<stdlib.h> #include<math.h> int main() { int p,i,n,t,x,y,u; scanf("%d",&p); i=0; n=0; t=1; while(n<32) { if((p&t)==t) { i++; } else ; n++; t=pow(2,n); } if(i==0||i==1) { y=i; u=32; } else if(i%2!=0) { y=i; u=32; } else { for(x=2; i>=x;) { if(i%x==0) { y=i/x; u=32/x; } x=2*x; } } printf("%d,%d:%d\n",i,y,u); return 0; }
首先值得肯定的是,在没有学过用递归写最大公约数的情况下,能够针对“32是2的5次幂”来分类约分,是很不容易的。并且分类的方法是对的,也就是说,约分部分的程序是对的。
但是,程序的可读性极差。大括号的对齐习惯不是最主要的原因,主要是因为变量名毫无意义,一堆a、b、c、i、p、u,没有人知道是什么意思。
所以,下面说说一般情况下被广为接受的惯用命名法。初学者应该特别注意变量的命名,绝对不能取没有意义的变量名,并且建议不要把循环变量i用作计数器(除非很清楚自己在做什么),以及写上必要的注释。当然,每个人也都会有自己的偏好习惯,所以这些命名法仅供参考。
<
pre class=”lang:xhtml decode:true”>数组
a[]
arr[]
array[]
data[]
e[]
m[]
mat[]
mtx[]
matrix[]
最终答案的临时存储
ans
answer
平均值
ave
avg
average
普通数值
a
b
计数器
c
cnt
count
counter
tot
total
字符
ch
距离
dist
磁盘
disk
深度优先搜索
dfs
被除数
dividend
除数
divisor
动态规划
dp
编辑
edt
edit
editor
没有明确含义的布尔逻辑值(必要时要加注释)
f
flag
有明确含义的布尔逻辑值
isXXX
并且用1表示something is XXX,用0表示something is not XXX
如:
isnew
isprime
isexist
isopen
isfinished
ismore
没有明确含义的函数(必要时要加注释)
f
fac
fact
fct
func
群组
g
grp
gpe
group
最大公约数
gcd
循环变量
i
ii
j
jj
k
kk
定位符
loc
location
长度
len
length
需要输入获取的数据
m
n
num
最大值
max
最小值
min
管理
mgmt
management
指针
p
pt
lnk
link
快速排序
qs
qsort
q_sort
quicksort
余数
rest
返回值
ret
字符串
s
st
str
累加
sum
临时变量
t
tmp
temp
计时器
t
time
mmt
moment
未知量(常见于函数参数表)
x
y
z
并且,变量一般用小写字母,如ans;常量一般用大写字母,如NUMBER、PI、BEGIN;逻辑真与逻辑假一般用全大写,如TRUE、FALSE。
你写的我们好像。。。你懂得