哈工大C语言Mooc 第九周 指针
练兵区–编程题
1二分法求根(4分)
题目内容:
用二分法求下面的一元三次方程在区间[-10, 10]上误差不大于的根。
#include<stdio.h>
#include<string.h>
#include<string.h>
float getX(float left, float right,float (*f)(float));
float getFx(float x);
int main(){
float left, right;
scanf( "%f,%f", &left, &right);
float res = getX(left, right, getFx);
printf( "x=%6.2f\n", res);
return 0;
}
float getX(float left, float right,float (*f)(float)){
float middle, fx;
while(1){
middle = (left + right) / 2;
fx = getFx(middle);
if(fabs(fx) <= pow(10, -6)){
return middle;
}
if(fx > 0){
right = middle;
}
else if(fx < 0){
left = middle;
}
}
}
float getFx(float x){
return pow(x, 3) - x - 1;
}
2矩阵转置(4分)
题目内容:
某二维数组存放的数据构成一个nn的方阵,其中n<=5。写程序,从键盘输入n的值(n<=5),该nn矩阵中各元素的值按下面的公式计算:
a[i][j] = i * n + j + 1
其中,a[i][j]
表示第i行第j列的元素。要求分别输出该矩阵和它的转置矩阵。
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include <malloc.h>
#include <time.h>
#include<string.h>
#define N 5
void drawOriginal(int n,int arr[][N]);
void drawChange(int n,int arr[][N], int transposeMatrix[][N]);
void drawMatrix(int n, int arr[][N]);
int main(){
int input;
int a[N][N], transposeArr[N][N];
memset(a, 0, sizeof(a));
memset(transposeArr, 0, sizeof(transposeArr));
scanf("%d", &input);
drawOriginal(input, a);
drawChange(input, a, transposeArr);
printf("The original matrix is:\n");
drawMatrix(input, a);
printf("The changed matrix is:\n");
drawMatrix(input, transposeArr);
return 0;
}
void drawOriginal(int n,int arr[][N]){
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
arr[i][j] = i*n + j +1;
}
}
}
void drawChange(int n,int arr[][N], int transposeMatrix[][N]){
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
transposeMatrix[i][j] = i + 1 + j*n;
}
}
}
void drawMatrix(int n, int arr[][N]){
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
printf("%3d", arr[i][j]);
}
printf("\n");
}
}
3程序改错(4分)
题目内容:
下面程序的功能是从键盘任意输入n个数,然后找出其中的最大数与最小数,并将其位置对换。目前程序中存在错误,请修改正确。并按照给出的程序运行结果示例检查修改后的程序。
#include<stdio.h>
#include<string.h>
#define ARR_SIZE 10
int main() {
int a[ARR_SIZE], i, n;
printf("Input n(n<=10):\n");
scanf("%d", &n);
printf("Input %d Numbers:\n", n);
for (i=0; i<n; i++) {
scanf("%d", &a[i]);
}
MaxMinExchang(a, n);
printf("After MaxMinExchange:\n");
for (i=0; i<n; i++) {
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
void MaxMinExchang(int *a, int n) {
int maxValue = a[0], minValue = a[0], maxPos = 0, minPos = 0;
int i, temp;
for (i=0; i<n; i++) {
if (a[i] > maxValue) {
maxValue = a[i];
maxPos = i;
}
if (a[i] < minValue) {
minValue = a[i];
minPos = i;
}
}
temp = a[maxPos];
a[maxPos] = a[minPos];
a[minPos] = temp;
}
4蛇形矩阵(4分)
题目内容:
从键盘任意输入一个自然数n(n表示矩阵的大小,假设不超过100),请编程输出一个n*n的蛇形矩阵。如果输入的n不是自然数或者输入了不合法的数字,则输出"Input error!"。
#include<stdio.h>
#include<string.h>
#include<string.h>
#define N 100
void ZigzagMatrix(int arr[][N], int n);
void printMatrix(int arr[][N], int n);
int main(){
int input, arr[N][N];
memset(arr, 0, sizeof(arr));
printf("Input n:\n");
int flag = scanf("%d", &input);
if(flag < 1||input <= 0||input > 100){
printf("Input error!\n");
return 0;
}
ZigzagMatrix(arr, input);
printMatrix(arr, input);
return 0;
}
void printMatrix(int arr[][N], int n){
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
printf("%4d", arr[i][j]);
}
printf("\n");
}
}
void ZigzagMatrix(int arr[][N], int n){
int flag = 0, len = 1, x = 0, y = 0;
arr[0][0] = 1;
while(1){
if(len == n*n) { // end condition
return 0;
}
// 右移动
if(flag == 0){
arr[x][++y] = ++len;
// 斜向移动
if(x == 0){
// 向左下移动
while(y > 0){
arr[++x][--y] = ++len;
}
}else if(x == n-1){
// 向右上移动
while(y < n-1){
arr[--x][++y] = ++len;
}
}
if(!(x==n-1&&y==0)){
flag = 1;
}
}
// 下移动
else if(flag == 1){
arr[++x][y] = ++len;
// 斜向移动
if(y == 0){
// 向右上移动
while(x > 0){
arr[--x][++y] = ++len;
}
}else if(y == n-1){
// 向左下移动
while(x < n-1){
arr[++x][--y] = ++len;
}
}
if(!(x==0&&y==n-1)){
flag = 0;
}
}
}
}
- 逻辑很关键,而且要学会用调试,找出边界的问题。
- 递归小改一下就是了,我就不写了。
5亲密数_1(4分)
题目内容:
2500年前数学大师毕达哥拉斯就发现,220与284两数之间存在着奇妙的联系:
220的真因数之和为:1+2+4+5+10+11+20+22+44+55+110=284
284的真因数之和为:1+2+4+71+142=220
毕达哥拉斯把这样的数对称为相亲数。相亲数,也称为亲密数,如果整数A的全部因子(包括1,不包括A本身)之和等于B,且整数B的全部因子(包括1,不包括B本身)之和等于A,则将整数A和B称为亲密数。
从键盘任意输入两个整数m和n,编程判断m和n是否是亲密数。若是亲密数,则输出“Yes!”,否则输出“No!”
#include<stdio.h>
#include<string.h>
#include<string.h>
int getSum(int n);
int main(){
int a, b, resA, resB;
printf("Input m, n:\n");
scanf("%d,%d", &a, &b);
resA = getSum(a);
resB = getSum(b);
if(resA == b&&resB==a){
printf("Yes!\n");
}else{
printf("No!\n");
}
return 0;
}
int getSum(int n){
if(n == 1) return 0;
int scope = sqrt(n), sum = 1;
for(int i = 2; i < scope; i++){
if(n % i == 0){
sum = sum + i + n / i;
}
}
return sum;
}
6亲密数_2(4分)
题目内容:
2500年前数学大师毕达哥拉斯就发现,220与284两数之间存在着奇妙的联系:
220的真因数之和为:1+2+4+5+10+11+20+22+44+55+110=284
284的真因数之和为:1+2+4+71+142=220
毕达哥拉斯把这样的数对称为相亲数。相亲数,也称为亲密数,如果整数A的全部因子(包括1,不包括A本身)之和等于B,且整数B的全部因子(包括1,不包括B本身)之和等于A,则将整数A和B称为亲密数。
从键盘任意输入一个整数n,编程计算并输出n以内的全部亲密数。
#include<stdio.h>
#include<string.h>
#include<string.h>
int getSum(int n);
int main(){
int input, resA, resB;
printf("Input n:\n");
scanf("%d", &input);
for(int i = 2; i <= input;i++){
resA = getSum(i);
if(resA > i&&resA <= input){
resB = getSum(resA);
if(resB == i)
{
printf("(%d,%d)\n", i, resA);
}
}
}
return 0;
}
int getSum(int n){
if(n == 1) return 0;
int scope = sqrt(n), sum = 1;
for(int i = 2; i < scope; i++){
if(n % i == 0){
sum = sum + i + n / i;
}
}
return sum;
}
- 思路其实很简单,但是你要两层for肯定是不行的,效率太低了。
- 一层for就够了,对遍历到的值求真因数和,如果这个值比它大就去看这个真因数和的真因数和是否等于当前遍历值即可。
- 如果遍历到的值真因数和小于当前遍历值,如果它满足要求,那么它一定已经被找到了。
7完全数(4分)
题目内容:
完全数(Perfect Number),又称完美数或完数,它是指这样的一些特殊的自然数。它所有的真因子(即除了自身以外的约数)的和,恰好等于它本身,即m的所有小于m的不同因子(包括1)加起来恰好等于m本身。注意:1没有真因子,所以1不是完全数。计算机已经证实在10300以下,没有奇数的完全数。例如,因为6 = 1 + 2 + 3,所以6是一个完全数。
#include<stdio.h>
#include<string.h>
#include<string.h>
#define N 100
int getSum(int n, int arr[]);
int main(){
int input, arr[N];
memset(arr, 0, sizeof(arr));
printf("Input m:\n");
scanf("%d", &input);
if(input % 2 == 1&& input < 10300){ // Take full advantage of known
printf("No!\n");
return 0;
}
if(getSum(input, arr) == input){
printf("Yes!\n");
for(int i = 0;arr[i]>0 && i< N;i++){
if(arr[i+1] == 0) printf("%d", arr[i]);
else printf("%d,", arr[i]);
}
}else{
printf("No!\n");
}
return 0;
}
int getSum(int n,int arr[]){
if(n == 1) return 0;
int total = 1;
arr[0] = 1;
int sum = 1;
for(int i = 2; i < n; i++){
if(n % i == 0){
sum = sum + i;
arr[total] = i;
total++;
}
}
return sum;
}
写得很不严谨,不过可以通过测试。
8回文素数(4分)
题目内容:
所谓回文素数是指对一个素数n,从左到右和从右到左读是相同的,这样的数就称为回文素数,例如11,101,313等。编程计算并输出不超过n(100<=n<1000)的回文素数,并统计这些回文素数的个数,其中n的值从键盘输入。
#include<stdio.h>
#include<string.h>
#define N 20
int isPrime(int n);
int isPalindrome(int n);
int main(){
int input, count = 0, arr[N];
memset(arr, 0, sizeof(arr));
printf("Input n:\n");
scanf("%d", &input);
if(input >= 1000&&input < 100){
printf("Not within the value range!");
return 0;
}
for(int i = 2; i <= input; i++){
if(isPrime(i)&&isPalindrome(i)){
arr[count] = i;
count++;
}
}
for(int i = 0; i < 20; i++){
if(arr[i] == 0) break;
printf("%4d", arr[i]);
}
printf("\ncount=%d\n", count);
return 0;
}
int isPrime(int n){
int scope = sqrt(n);
for(int i = 2; i <= scope; i++){
if(n % i == 0){
return 0;
}
}
return -1;
}
int isPalindrome(int n){
int arr[3] = {0};
arr[2] = n / 100;
arr[1] = n % 100 / 10;
arr[0] = n % 10;
if(arr[2] == 0){
return arr[0] == arr[1];
}
else return arr[0] == arr[2];
}
- 其实回文问题很有意思的,之前写过最长回文子串的coding,从最开始的O(n3)-三层
for
循环,优化到O(n1)-Manacher
9梅森尼数(4分)
题目内容:
形如2i-1的素数,称为梅森尼数。编程计算并输出指数i在[2,n]中的所有梅森尼数,并统计这些梅森尼数的个数,其中n的值由键盘输入,并且n的值不能大于50。其中,2i表示2的i次方,请不要使用pow(2,i)
编程计算,应采用循环累乘求积的方式计算2^i
。
提示:当i 超过30以后,2i-1的值会很大,不能用long型变量来存储,必须使用double类型来存储。对于double类型变量x(不是整型)不能执行求余运算,即不能用 x % i == 0
来判断x是否能被i整除,可以使用 x / i == (int)(x/i)
来判断x是否能被i整除。
#include<stdio.h>
int isPrime(double n);
int main(){
int input, count = 0;
printf("Input n:\n");
scanf("%d", &input);
double twoPow= 2;
for(int i = 2; i <= input; i++){
twoPow *= 2;
if(isPrime(twoPow - 1) == -1){
printf("2^%d-1=%.0lf\n", i, twoPow - 1);
count++;
}
}
printf("count=%d\n", count);
return 0;
}
int isPrime(double n){
double scope = sqrt(n);
for(int i = 2; i < scope; i++){
if(n / i == (int)(n/i)){
return 0;
}
}
return -1;
}
10工资统计(4分)
题目内容:某公司有职员(最多50人),试编写程序打印最高工资、最低工资和平均工资。公司人数在主函数给出,职工工资输入请调用Input函数,计算最高工资、最低工资和平均工资调用Compute函数,打印最高工资、最低工资和平均工资在主函数。
#include<stdio.h>
void Input(float wage[], int n);
float Compute(float wage[], int n, float *pmaxwage, float *pminwage);
int main()
{
float wage[50],maxwage,minwage,avewage;
int n;
printf("Please input n:\n");
scanf("%d",&n);
Input(wage, n);
avewage=Compute(wage, n, &maxwage, &minwage);
printf("maxwage=%.2f, minwage=%.2f, avewage=%.2f\n",maxwage,minwage,avewage);
return 0;
}
void Input(float wage[], int n)
{
for(int i = 0; i < n; i++){
scanf("%f", &wage[i]);
}
}
float Compute(float wage[], int n, float *pmaxwage, float *pminwage){
int maxIndex = 0, minIndex = 0;
float sum = 0;
for(int i=0; i < n; i++){
sum += wage[i];
if(wage[i] > wage[maxIndex]){
maxIndex = i;
}
if(wage[i] < wage[minIndex]){
minIndex = i;
}
}
*pmaxwage = wage[maxIndex];
*pminwage = wage[minIndex];
return sum / n;
}
第9周编程题在线测试
1重复数字检查(4分)
题目内容:
从键盘输入一个数,检查这个数中是否有重复出现的数字。如果这个数中有重复出现的数字,则显示“Repeated digit!”;否则显示“No repeated digit!”。
自己写的用例2一直过不了,找了一个code:Answer
- 问题code,希望有人看到可以看一下问题在哪。
#include<stdio.h>
#include<string.h>
#include<math.h>
#define N 10
int CountRepeatNum(int count[], int n);
int main(){
long input, count[N];
int digit;
memset(count, 0, sizeof(count));
printf("Input n:\n");
scanf("%ld", &input);
input = abs(input);
while(input > 0){
digit = input % 10;
count[digit]++;
input = input / 10;
}
if(CountRepeatNum(count, N) == 0){
printf("No repeated digit!\n");
} else {
printf("Repeated digit!\n");
}
return 0;
}
int CountRepeatNum(int count[], int n){
for(int i = 0; i < n; i++){
if(count[i] > 1) return -1;
}
return 0;
}
2教授的课(4分)
题目内容:
教授正在为一个有N个学生的班级讲授离散数学课。他对某些学生缺乏纪律性很不满意,于是决定:如果课程开始后上课的人数小于K,就取消这门课程。从键盘输入每个学生的到达时间,请编程确定该课程是否被取消。如果该门课程被取消,则输出“Yes”,否则输出“No”。假设教授在时刻0开始上课。如果一个学生的到达时间是非正整数,则表示该学生在上课前进入教室。如果一个学生的到达时间是正整数,则表示该学生在上课后进入教室。如果一个学生在时刻0进入教室,也被认为是在上课前进入教室。假设到达时间的绝对值不超过100,学生数N不超过1000。要求在输入学生的到达时间之前,先输入N和K。
#include<stdio.h>
#include<string.h>
#include<math.h>
#define N 1000
int IsCancel(int a[], int n, int k);
int inputArrive(int a[], int n);
int checkWetherCancel(int a[], int n, int k);
int main(){
int n, k, a[N];
printf("Input n,k:\n");
scanf("%d,%d", &n, &k);
inputArrive(a, n);
if(checkWetherCancel(a, n, k) == -1){
printf("YES");
}else{
printf("NO");
}
return 0;
}
int inputArrive(int a[], int n){
for(int i = 0; i < n; i++){
scanf("%d", &a[i]);
}
}
int checkWetherCancel(int a[], int n, int k){
int count = 0;
for(int i = 0; i < n; i++){
if(a[i] <= 0){
count++;
}
}
if(count < k){
return -1;
}
return 0;
}
3寻找鞍点(4分)
题目内容:
请编程找出一个M*N矩阵中的鞍点,即该位置上的元素是该行上的最大值,是该列上的最小值。如果矩阵中没有鞍点,则输出“No saddle point!”
#include<stdio.h>
#include<string.h>
#include<math.h>
#define N 50
void FindSaddlePoint(int a[][N], int m, int n);
void inputMatrix(int a[][N], int m, int n);
int main(){
printf("Input m,n:\n");
int m, n, arr[N][N];
scanf("%d,%d", &m, &n);
inputMatrix(arr, m, n);
FindSaddlePoint(arr, m, n);
return 0;
}
void inputMatrix(int a[][N], int m, int n){
printf("Input matrix:\n");
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
scanf("%d", &a[i][j]);
}
}
}
void FindSaddlePoint(int a[][N], int m, int n){
// get max of every row; get min of every column
int maxOfEveryRow[N], minOfEveryColumn[N], maxPos, minPos;
// get max of every row;
for(int i = 0; i < m; i++){
maxPos = 0;
for(int j = 1; j < n; j++){
if(a[i][j] > a[i][maxPos]){
maxPos = j;
}
}
maxOfEveryRow[i] = a[i][maxPos];
}
// get min of every column
for(int i = 0; i < n; i++){
minPos = 0;
for(int j = 1; j < m; j++){
if(a[j][i] < a[minPos][i]){
minPos = j;
}
}
minOfEveryColumn[i] = a[minPos][i];
}
int flag = 0;
// traverse array element
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(a[i][j]==maxOfEveryRow[i]&&a[i][j]==minOfEveryColumn[j]){
printf("a[%d][%d] is %d\n", i, j, a[i][j]);
if(flag == 0) flag = 1;
}
}
}
if(flag == 0) printf("No saddle point!\n");
}
4计算三位阶乘和数(4分)
题目内容:
试求出所有三位阶乘和数:m=a!+b!+c!(其中a为百位数字,b为十位数字,c为个位数字。约定0!=1,并输出所有的m)
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include <malloc.h>
#include <time.h>
#include<string.h>
void calculateFactorialSum();
int Factorial(int n);
void calculateFactorialSum(){
int arr[3], one, hundred, ten;
for(int i = 100; i < 1000; i++){
one = i % 10;
ten = i / 10 % 10;
hundred = i / 100;
if(i == Factorial(one) + Factorial(ten) + Factorial(hundred)){
printf("%ld\n", i);
}
}
}
int Factorial(int n){
int res = 1;
if(n == 0){
return res;
}
for(int i = 1; i <= n; i++){
res *= i;
}
return res;
}
int main(){
calculateFactorialSum();
return 0;
}