PS:本题解是直接粘贴oj上通过了的代码,也就是考场上做出来的。部分方法比较笨,也是考场上我的第一反应,敬请谅解。

问题 A: 非线性方程牛顿法求解

时间限制: 1 Sec 内存限制: 128 MB

提交: 1130 解决: 112

[提交][状态][讨论版]

题目描述

用指向函数的指针设计通用非线性方程牛顿法求解函数Newton(f,df,x),求任意非线性方程f(x)=0在初始值x0附近的近似解,要求近似解精确到epsilon(1E-5)。其原型如下:

double Newton (double (*fun)(double), double (*dfun)(double),double x0);

其中,fun是指向原函数f(x)的函数指针,dfun是指向导函数f'(x)的函数指针,x0是求解方程近似解的初始值。

说明:非线性方程牛顿法求解公式如下:

xk+1 = xk – f(xk)/ f'(xk)

其中,xk表示第k步的x值,xk+1表示第k+1步的x值,f(xk)为原函数在xk处的值,f'(xk)为导函数在xk处的值。

当xk+1-xk的绝对值小于epsilon时,结束迭代,得到近似解xk+1。当在xk处的导函数值小于epsilon时,认为零作为了除数,直接返回INF(即return 1.0/0.0;,该语句用于返回INF)。

在已给出的代码中,f1()、df1()、f2()、df2()、f3()和df3()6个C语言函数分别用于计算如下3个数学函数f1(x) = x3 – 10×2 + 3x + 20、f2(x) = x3 – 6x – 1f3(x) = x3 + 10x – 20及其导函数的在指定x处的值。

程序主框架如下(提交时不要包含在内):

#include #include #include double f1(double);double df1(double);double f2(double);double df2(double);double f3(double);double df3(double);double Newton(double (*fun)(double), double (*dfun)(double), double x0); int main() { double x0; int n; scanf("%d%lf",&n,&x0); switch(n) { case 1: printf("%.5f\n", Newton(f1,df1,x0)); break; case 2: printf("%.5f\n", Newton(f2,df2,x0)); break; case 3: printf("%.5f\n", Newton(f3,df3,x0)); break; default: printf("error1\n"); exit(0); } return 0; } double f1(double x) { return x*x*x-10*x*x+3*x+20.0; } double df1(double x) { return 3*x*x-20*x+3; }double f2(double x) { return x*x*x-6*x-1; }double df2(double x) { return 3*x*x-6; }double f3(double x) { return x*x*x+10*x-20; }double df3(double x) { return 3*x*x+10; }

输入

一个整数和一个双精度数,其中整数代表要求解的非线性方程的编号(1~3),双精度数为方程求解x0的初始值

输出

方程的近似解,精确到小数点后5位

说明:输出格式由题目框架设定,无需关注输出格式。

样例输入

1 -1

样例输出

-1.20865

题解

double Newton (double (*fun)(double), double (*dfun)(double),double x0){double x1=0,s=0;s=fun(x0)/dfun(x0);x1=x0-s;if(fabs(dfun(x0)) < 1e-5)return 1.0/0.0;if(fabs(s) < 1e-5)return x1;else{x0=x1;return Newton(fun,dfun,x0);}}

反思

本题卡的两个点:

  1. 在最后递归时要记得把x1的值传给新的x0,让新x0等于旧x1,让x0更新换代起来;

  1. 此题一开始我在本地测试答案一直都是-1.0000,原因是一开始的先入为主,把x1定义为整型变量了,那么返回的x1值就小数点不可能有数字了,注意x1、s要定义为double型;

注意:本题主函数中有库,fabs函数(绝对值函数)直接用,并且用对;

问题 B: Luhn算法证件号码校验

时间限制: 1 Sec 内存限制: 128 MB

提交: 1474 解决: 157

[提交][状态][讨论版]

题目描述

Luhn算法是一种广泛使用的证件号码(由若干数字组成,长度不定)“模10”校验算法。其计算过程为:

1、从卡号最未位数字开始,逆向将奇数位(1、3、5等)求和。

2、从卡号最未位数字开始,逆向将偶数位数字乘2后求和(说明:如果乘2得到的是两位数,则将乘2的结果减9后参与求和)。

3、将奇数位和与偶数位和相加,通过判断相加结果是否是10的整数倍实现校验。

例如对于卡号5432123456788881,其各位数字编号如下表所示:

则其“模10”校验计算过程为:

1、奇数位和 = 1+8+8+6+4+2+2+4 = 35

2、偶数位和 = (8*2-9)+(8*2-9)+(7*2-9)+(5*2-9)+(3*2)+(1*2)+(3*2)+(5*2-9)

= 7+7+5+1+ 6+2+6+1 = 35

3、奇数位和+偶数位和=35+35=70, 结果是10的整数倍,校验通过。

请编写函数CheckLuhn(),完成若干组证件号码的Luhn校验,要求函数原型为:

int CheckLuhn(const char * cardId , int sum[2]);

其中,cardId是待校验证件号码字符串,sum是由两个元素构成的整型数组,sum[0]用于存储奇数位和,sum[1]用于存储偶数位和。如果通过校验,函数返回0,否则返回1。

请在已给出的宏定义、函数原型、驱动main函数代码的基础上完成题目。

程序主框架如下(注意,只提交题目要求的函数):

#include #include #include #define MAX_LEN 128int CheckLuhn ( const char * cardId, int sum[2] );int ReadLine(char *s);int ReadLine(char *s){int n = 0, ch = 0;while((ch = getchar()) != '\n' && ch != EOF && n  0) {r = CheckLuhn(id, s);printf("%s,R=%d\t%d\t%d\n", id, r, s[0], s[1]);}return 0;}

输入

若干行号码字符串

输出

四部分内容。第一部分为校验号码,第二部分为校验结果,第三、第四部分分别为奇数位和与偶数位和。

说明:输出格式由题目框架设定,无需关注输出格式。

样例输入

4342560238811238

样例输出

4342560238811238,R=0 32 38

提示

注意:在设计的函数中不需要进行任何数据输出,如需查看运算结果,请在提交前删除相关数据输出代码。

题解

int CheckLuhn(const char * cardId , int sum[2]){int n,i,mn=0,s=0;sum[0]=sum[1]=0;n=strlen(cardId);if(n%2 == 0){for(i = 0;i = '5')mn=(cardId[i]-48)*2-9;else mn=(cardId[i]-48)*2;sum[1]=sum[1]+mn;}}s=sum[0]+sum[1];if(s % 10 == 0)return 0;else return 1;}if(n%2 != 0){for(i = 0;i = '5')mn=(cardId[i]-48)*2-9;else mn=(cardId[i]-48)*2;sum[1]=sum[1]+mn;}}}s=sum[0]+sum[1];if(s % 10 == 0)return 0;else return 1;}

反思

本题卡的点:

一定一定在卡的时候要认真读题,认真看题目给的图。对应好每一位。一开始我只考虑了题目给的两个样例,这两个样例恰好都是16位(偶数位),我的错误代码就都跑的通,但提交之后答案错误。我就自己试图写了个样例“123”,一共有3位,发现到奇数位个码的话,跟偶数位就恰好是相反的(因为指针第一个数一直都是从0开始的),这个时候要把奇数位重新考虑,就只是跟偶数位的思路一样,反一下就行。

注意:本题输入的是字符串,运算时数字对应的是其ASCII码值,所以记得减去48得到数字本身值。

问题 C: 机动车车辆限行检测

时间限制: 1 Sec 内存限制: 128 MB

提交: 989 解决: 98

[提交][状态][讨论版]

题目描述

机动车车牌由3部分组成,分别是:省份简称、地级市字母代码、6位或5位车牌号(由大写字母和数字组成,新能源汽车为6位车牌号,普通车辆为5位车牌号),车牌号至少包含一位数字。根据车牌号实现机动车车辆限行,其规则如下: 新能源汽车不限号;普通车辆星期一限行尾号1和6,星期二限行尾号2和7,星期三限行尾号3和8,星期四限行尾号4和9,星期五限行尾号5和0,星期六和星期天所有车辆均不限行。

车牌尾号为车牌中数字的最后一位,如果车牌号最后一位不是数字,则从后往前找到的第一个数字即为车牌尾号。例如03D4J的尾号为4。

现要求编写机动车车辆限行检测函数,其原型如下:

int Judge(char *plate_num, int day);

其中,plate_num是用来存储车牌号的字符串指针,day代表星期的整型量(1~7分别代表星期一到星期日)。

当plate_num(长度小于5或大于6、不包含数字、包含非法字符)或day(小于1或大于7)错误时,返回-1;当该车牌号被限行时,返回1,否则返回0。

主程序框架如下:

#include #include #define MAX_LEN 10int Judge(char *, int);int ReadLine(char *s);int ReadLine(char *s){int n = 0, ch = 0;while((ch = getchar()) != '\n' && ch != EOF && n  0){scanf("%d", &n); /* 星期 */getchar();printf("%d\n", Judge(str, n));}return 0;}

输入

输出

说明:输出格式由题目框架设定,无需关注输出格式。

提示

注意:在设计的函数中不需要进行任何数据输出,如需输出运算结果,请在提交前删除相关代码.

题解

int Judge(char *plate_num, int day){int n,i,j,k;n=strlen(plate_num);if(n6 || day7)return -1;for(i = 0;i < n;i++){if(plate_num[i]  '9' && plate_num[i]  'Z')return -1;}for(j = 0;j = '0' && plate_num[j] = 0;k--){if(plate_num[k] >= '0' && plate_num[k] <= '9'){if(day == 1){if(plate_num[k] == '1' || plate_num[k] == '6')return 1;else return 0;}if(day == 2){if(plate_num[k] == '2' || plate_num[k] == '7')return 1;else return 0;}if(day == 3){if(plate_num[k] == '3' || plate_num[k] == '8')return 1;else return 0;}if(day == 4){if(plate_num[k] == '4' || plate_num[k] == '9')return 1;else return 0;}if(day == 5){if(plate_num[k] == '5' || plate_num[k] == '0')return 1;else return 0;}if(day == 6 || day == 7)return 0;}}}}

反思

本题是我做出来三道题中,第一个有思路的,也是第一个做的题(我是从后往前做的)

本题卡的点:

一开始注意到了“从后往前找到的第一个数字即为车牌尾号”自己写代码的时候就又忘了,本题也没有输入,就硬着头皮交了一次,显示通过了80%,后来第一反应到自己是这错了把for循环条件改了一下,还好反应的快,没有了浪费时间。

其他这道题就没有什么了,疯狂码字而已,注意n,day,plate_num[]分别代表什么别搞混就行。注意for(i = n;i >= 0;i–)就好,此次考试两题的for循环都是从后往前,打破以往常规。

问题 D: 水果店库存排序

时间限制: 1 Sec 内存限制: 128 MB

提交: 207 解决: 20

[提交][状态][讨论版]

题目描述

某水果店使用文本文件记录每种水果的进货和出货量(单位:公斤),文件中的每一行表示一种水果记录,各行第一列表示水果名称,第二列、第三列分别表示进货量和出货量,各列间用空白分隔。假设水果已归类,不存在重复现象。例如:

Apple 50.5 20.3

Banana 30 10.2

Orange 100 80.6

为实现水果店库存排序,要求编写如下两个函数:

1、文件读取函数,其原型如下:

int loadStock(pFInfo stocks, const char *fname);

其中,stocks是结构体类型的指针,用于存储读取的库存记录,fname是需要读取的水果库存记录文本文件的文件名指针,如”record.txt”。函数返回成功读取的记录条数。假定stocks指针指向的内存空间已经预先分配。

2、按照水果库存量(库存量=进货量-出货量)降序对记录进行排序并输出到指定文件的函数,其原型如下:

void sortAndSaveStock(pFInfo stocks, int n, char *fname);

其中,stocks是结构体类型的指针,用于存储读取的库存记录,n是水果库存记录总数,fname是指定的输出文本文件的文件名指针,如”sorted_record.txt”。输出时所有小数保留1位小数。

文本文件样例可使用wget命令在SSH环境中获取,命令: wget http://202.117.179.201/attach/record.txt

程序主体框架如下(注意只提交题目要求的函数):

#include #include #define MAX_NAME_LEN 20#define MAX_FRUIT_LEN 20typedef struct{char name[MAX_NAME_LEN];float in;float out;}FInfo, *pFInfo;int loadStock(pFInfo, const char *);void sortAndSaveStock(pFInfo, int, char *);int main(int argc, char *argv[]){FInfo fruitStock[MAX_FRUIT_LEN];if (argc < 3){printf("Usage: %s  \n", argv[0]);exit(EXIT_FAILURE);}/* read stock information from txt file */int n = loadStock(fruitStock, argv[1]);if ( n > 0)sortAndSaveStock(fruitStock, n, argv[2]);return 0;}

输入

输出

说明:在设计的函数中无需任何控制台输出,文件输出时所有数值量均保留一位小数,水果名称、进货量与出货量间用一个空格分隔,每个水果一行,最后一行无换行

提示

注意:在设计的函数中不需要进行任何数据输出至显示器,如需在显示器上输出运算结果,请在提交前删除相关代码。 在文件写入的时候,注意不要加入任何多余的字符(回车、换行及空格等)。

问题 E: 英文句子按单词实现反转

时间限制: 1 Sec 内存限制: 128 MB

提交: 110 解决: 14

[提交][状态][讨论版]

题目描述

现需要对一个以’.’、’?’或’!’为终止字符的英文句子按单词实现反转。现假定:

1、每次反转只针对一行完整的句子,如果输入不是一个完整句子,则输出”Sentence needs a terminating character. (./?/!)\n\n”;

2、所有句子均无前导后续分隔符;

3、除终止符和分隔符外,其它标点符号与单词被认为是一个整体,并且不能独立存在。

如:

原文为:I like C langage, but he is only interested in football.

反转为:football in interested only is he but langage, C like I.

程序主体已经完成,要求实现如下两个函数:

1、单词分割及提取函数,其原型如下:

char ** splitSentenceWords(char *str , const char *delim, size_t n);

其中,str为指向句子原文字符串的指针,delim为指向可能出现的单词分隔符构成的字符串的指针,n为单词个数。函数返回分割结果的字符型二级指针。函数调用完成后,必须手工释放返回的二级指针指向的指针数组占用的内存。

2、句子按单词反转函数,其原型如下:

char * revSentenceWords(char *str, const char *delim, const char *hyphen);

其中,str为指向句子原文字符串的指针,delim为指向可能出现的单词分隔符构成的字符串的指针,hyphen指向结果句子中连接各单词的字符串。函数返回指向反转结果的指针。函数调用完成后,必须手工释放返回的指针指向的字符串占用的内存。

程序主体框架如下(注意只提交自己补足的函数代码,下面的代码请勿提交):

#include #include #include #define MAXLENGTH 1024char* revSentenceWords(char *, const char *, const char *);char** splitSentenceWords(char *, const char *, size_t);char isSentence(const char *, const char *);size_t getWordsCnt(const char *, const char *);int ReadLine(char *, int);int ReadLine(char *str, int len){int n = 0, ch = 0;while((ch = getchar()) != EOF && ch != '\n' && n < len - 1)str[n++] = ch;str[n]='\0';return n;}int main(void){char s[MAXLENGTH];char *p,**q;char delim[] = " \t\n\r";char term[] = ".?!";char hyphen[] = " ";int i, wc = 0;ReadLine(s, MAXLENGTH);if (isSentence(s, term)){p = revSentenceWords(s, delim, hyphen);puts(p);wc = getWordsCnt(p, delim);printf("WordsCnt= %d\n", wc);q = splitSentenceWords(p, delim, wc);for(i = 0; i < wc; i++){puts(q[i]);}free(q);free(p);}return(0);}char isSentence(const char *s, const char *term){char terminator = 0;size_t len = 0;len = strlen(s);terminator = s[len - 1];if(!strchr(term, terminator)){printf("Sentence needs a terminating character. (./?/!)\n\n");exit(1);}return terminator;}size_t getWordsCnt(const char *s, const char *delim){size_t cnt = 0;while(*s){if((!strchr(delim, *s) && (strchr(delim, *(s + 1)))) || (*(s + 1) == '\0' && (!strchr(delim, *s)))){cnt++;}s++;}return cnt;}

输入

输出

说明:输出格式由题目框架设定,无需关注输出格式。

提示

注意:在设计的函数中不需要进行任何数据输出,如需输出运算结果,请在提交前删除相关代码。

无题解

D、E两题考场上完全没有思路,总结来看还是对结构和文件这两张没学扎实。把问题先放到这儿,期待日后某天有能力再来解决这两道题