C2第二周练习

高级(C)语言程序设计2的第二次作业

这次作业难度比第一次还要略低一点,难度确实谈得上简单,不过从第三次感觉难度就在往上走了,因为自己做的时候已经感到有点棘手(可能也是因为太菜)。。。。不过按照老师的说法反正也不会出现太难的数据结构和算法(这俩我都不会),所以自己这水平应该能勉强应付一点吧。

这次只有五个编程大题了

螺旋矩阵

【问题描述】
输入一个自然数N(2≤N≤9),要求输出如下的螺旋矩阵,即边长为N*N,元素取值为1至N*N,1在左上角,呈顺时针方向依次放置各元素。
N=3时,相应的矩阵中每个数字位置如下图所示: 
1  2  3
8  9  4
7  6  5
【输入形式】
从标准输入读取一个整数N。
【输出形式】
向标准输出输出一个N*N的螺旋矩阵,即边长为N*N,元素取值为1至N*N,1在左上角,呈顺时针方向依次放置各元素,每个数字占5个字符宽度,向右对齐,不足部分补以空格。在每一行末均输出一个回车符。
【输入样例】
3
【输出样例】
####1####2####3 
####8####9####4 
####7####6####5 
(注:这里#代表空格的位置)
【时间限制】
1s
【空间限制】
65536KB
【上传文件】
上传c语言源程序,文件名为rotate.c。

这题之前做过了,唯一的坑点(或许都谈不上坑)可能是奇数和偶数的情况不一样得分开判断。

#include<stdio.h>
#define LINE 11

void Odd(int[][LINE], int);
void Even(int[][LINE], int);
void print(int[][LINE], int);

int main()
{
	int n;
	int a[LINE][LINE];
	scanf("%d", &n);

	if (n % 2)	Odd(a, n);
	else	Even(a, n);

	print(a, n);
}

void Odd(int a[][LINE], int n)
{
	int i, j;
	int num = 1;
	for (i = 1; i <= n / 2; i++)
	{
		for (j = i; j < n + 1 - i; j++)
		{
			a[i][j] = num++;
		}
		for (j = i; j < n + 1 - i; j++)
		{
			a[j][n + 1 - i] = num++;
		}
		for (j = n + 1 - i; j > i; j--)
		{
			a[n + 1 - i][j] = num++;
		}
		for (j = n + 1 - i; j > i; j--)
		{
			a[j][i] = num++;
		}
	}
	a[n / 2 + 1][n / 2 + 1] = num;
}

void Even(int a[][LINE], int n)
{
	int i, j;
	int num = 1;
	for (i = 1; i <= n / 2; i++)
	{
		for (j = i; j < n + 1 - i; j++)
		{
			a[i][j] = num++;
		}
		for (j = i; j < n + 1 - i; j++)
		{
			a[j][n + 1 - i] = num++;
		}
		for (j = n + 1 - i; j > i; j--)
		{
			a[n + 1 - i][j] = num++;
		}
		for (j = n + 1 - i; j > i; j--)
		{
			a[j][i] = num++;
		}
	}
}

void print(int a[][LINE], int n)
{
	int i, j;
	for (i = 1; i <= n; i++)
	{
		for (j = 1; j <= n; j++)
		{
			printf("%5d", a[i][j]);
		}
		printf("\n");
	}
}

判断出栈序列

【问题描述】
对于一个栈,已知元素的进栈序列,判断一个由栈中所有元素组成的排列是否是可能的出栈序列。
比如,进栈序列为1 2 3 4,则可能的出栈序列有4 3 2 1,1 4 3 2等。而1 4 2 3就不是。
【输入形式】
从标准输入读取输入。 第一行是一个整数N(3≤N≤10),代表有N个元素,其进栈序列是1 2 3 …… N。 第二行是以空格分隔的1~N的数字的一个排列。
【输出形式】
向标准输出打印结果。 如果该排列是可能的出栈序列,则打印“YES”,否则打印“NO”。在行末要输出一个回车符。
【输入样例】
4 
1 4 3 2
【输出样例】
YES
【时间限制】
1s
【空间限制】
65536KB
【上传文件】
上传c语言源程序,文件名为outstack.c。

开始的时候居然想错了= =

形如{1,4,3,5,2}这种情况也是可能出现的,所以做法就是直接模拟出栈顺序了。把1,2,3……压入栈中,如果跟输入序列的当前元素相等,就pop出来然后继续判断。如果最后栈空,表示元素全部出栈,也就是可能出现。栈我还是记得一点的所以简单手写了一个stack。

#include<stdio.h>
#define FULL 12

int stack[FULL];
int top = -1;

void push(int val)
{
	stack[++top] = val;
}

void pop() 
{
	top--;
}

int gettop()
{
	return stack[top];
}

void outstack(int a[], int n)
{
	int i;
	int a_index = 1;

	for (i = 1; i <= n; i++)
	{
		push(i);
		while (top > -1 && gettop() == a[a_index])
		{
			a_index++;
			pop();
		}
	}

	if (top == -1 && a_index == n + 1)
		printf("YES\n");
	else
		printf("NO\n");
}

int main()
{
	int a[12];
	int n, i;
	scanf("%d", &n);
	for (i = 1; i <= n; i++)
		scanf("%d", &a[i]);

	outstack(a, n);
}

N位质数

【问题描述】
给定一个整数N(2 <= N <= 8),生成所有的具有下列特性的特殊的N位质数:其前任意位都是质数。
例如,7331即是这样一个4位的质数,因为7、73和733也都是质数。
【输入形式】
标准输入上输入一个正整数N(2 <= N <= 8)。
【输出形式】
标准输出。 输出所有符合题意的N位质数,每个数占一行,且按升序排列。
【输入样例】
2
【输出样例】
23 
29 
31 
37 
53 
59 
71 
73 
79
【时间限制】
5s
【空间限制】
65536KB
【上传文件】
上传c语言源程序,文件名为nprime.c。

这次稍微难点的了,不过也不算太难,还是有点意思的题。

时间给了5s,比起其他的1s,可能是会出现超时的征兆。显然直接一个个判断是行不通的。由于N位质数的前任意位都是质数,那么我们可以从1位质数生成2位质数,接着生成3位质数……简单说来就是从前面的2、3、5、7后面一位位添加数字,每次添加后都是质数即可。

#include<stdio.h>
#include<string.h>
#include<stdbool.h>

bool isPrime(int);
void update(int[], int[]);

int main()
{
	int n, i;
	int a[200] = { 2,3,5,7 };
	int temp[200] = { 0 };
	scanf("%d", &n);

	for (i = 1; i < n; i++)
	{
		update(a, temp);
	}

	for (i = 0; a[i] != 0; i++)
		printf("%d\n", a[i]);
}


bool isPrime(int x)
{
	int i;
	if (x == 1)
		return 0;
	for (i = 2; i * i <= x; i++)
	{
		if (x % i == 0)
			return false;
	}
	return true;
}

void update(int a[], int temp[])
{
	int i, j;
	int num = 0;

	for (i = 0; a[i] != 0; i++)
	{
		for (j = 1; j <= 9; j++)
		{
			if (isPrime(a[i] * 10 + j))
			{
				temp[num++] = a[i] * 10 + j;
			}
		}
	}
 
	memset(a, 0, 200 * sizeof(int));

	for (j = 0; temp[j] != 0; j++)
		a[j] = temp[j];

	memset(temp, 0, 200 * sizeof(int));
}

泊松分布

【问题描述】
泊松分布是一种常用的离散型概率分布,数学期望为m的泊松分布的分布函数定义如下:
P(m, k) =   (k = 0, 1, 2, 3, …)
对于给定的m和k (0<m<2000, 0<= k < 2500),计算其概率,以科学格式输出,保留小数点后6位有效数字。
可以使用数学库函数,误差不超过0.000001。
【输入形式】
输入文件为当前目录下的poisson.in。 文件中包含两个数字,分别为m,k的值。
【输出形式】
输出文件为当前目录下的poisson.out。 文件中输出泊松分布的值,值以科学格式输出,保留小数点后6位有效数字。
【输入样例】
1 0
【输出样例】
3.678794e-01
【时间限制】
1s
【空间限制】
65536KB
【上传文件】
上传c语言源程序,文件名为poisson.c。

P(m,k) = m^{k}*e^{-m}/k!  公式贴不到代码段里面啊

一道坑题,A完之后我才知道有个%e的输出格式。主要我也不知道测试数据是啥,本地测了下%e跟第一次代码跑的结果有的不一样,然而都A了,也是很迷。

开始没有思路然后就硬算好了,我这里的思路在计算过程还是看得出来的,先算e^{-m},再乘m/i。然后用一个count来记录e后面的数字,结果也是过了。

#include<stdio.h>
#include<math.h>

void compute(int, int, double*, int*);

int main()
{
	FILE *in, *out;
	in = fopen("poisson.in", "r");
	out = fopen("poisson.out", "w");

	int m, k, cnt;
	double ans;

	fscanf(in, "%d%d", &m, &k);
	compute(m, k, &ans, &cnt);
	fprintf(out, "%.6lfe-%02d", ans, cnt);

	fclose(in); fclose(out);
	return 0;
}


void compute(int m, int k, double *answer, int *count)
{
	double ans = 1;
	int cnt = 0;
	int i;

	for (i = 0; i < m; i++)
	{
		ans /= exp(1);
		while (ans < 1)
		{
			ans *= 10;
			cnt++;
		}
	}

	if(k)
	{
		for (i = 1; i <= k; i++)
		{
			ans *= m;
			ans /= i;

			while (ans < 1)
			{
				ans *= 10;
				cnt++;
			}
			while (ans > 10)
			{
				ans /= 10;
				cnt--;
			}
		}
	}
	
	*answer = ans; *count = cnt;
}

然后我知道了一个叫%e的格式。

然后我知道了两边同时log的黑科技= = 用数学方法就能解决,具体代码如下,公式在注释里面

#include<stdio.h>
#include<math.h>

double compute(int, int);

int main()
{
	FILE *in, *out;
	in = fopen("poisson.in", "r");
	out = fopen("poisson.out", "w");

	int m, k;
	double ans;

	fscanf(in, "%d%d", &m, &k);
	ans = compute(m, k);
	fprintf(out, "%e\n", ans);

	fclose(in); fclose(out);
	return 0;
}

double compute(int m, int k)
{
	//ln(P) = klnm - m - (ln 1 + ln 2 + …… + ln k)
	int i;
	double ans;

	ans = k * log(m) - m;
	for (i = 1; i <= k; i++)
	{
		ans -= log(i);
	}
	ans = exp(ans);
	return ans;
}

嘛,,,原来有误差不超过0.000001的限制,算的精度也没必要那么高。

Cantor表的第n项

【问题描述】
现代数学的著名证明之一是Georg Cantor用下面这一张表证明了有理数是可枚举的。
以Z形方式顺序给表中的每一项编号。第一项是1/1,然后是1/2,2/1,3/1,2/2,…。
从标准输入上读入一个整数N(1≤N≤10000000),在标准输出上输出表中第N项所对应的分数。


【输入形式】
一个正整数,占一行,整数的前后均无空白符。
【输出形式】
以a/b形式表示的分数,以换行符结束。分数的前及各个字符间均无空格。
【输入样例】
9
【输出样例】
3/2
【时间限制】
1s
【空间限制】
65.536KB
【上传文件】
上传c语言源程序,文件名为cantor.c。

妈耶,,,这题水死我了,我代码都懒得改了直接贴上来算了。

#include<stdio.h>

int main()
{
	int n, low;
	scanf("%d",&n);
	
	for(low = 1;low < 5000;low++)
	{
		if(low * (low + 1) / 2 >= n)
			break;
	}
	//low为第x条斜线
	
	int high = low + 1; 
	//high为分子分母之和 
	
	int num = n - (low - 1) * low / 2;
	//num表示其在第low条第num个
	
	if(low % 2)
	{
		printf("%d/%d",high - num,num);
	}
	else
	{
		printf("%d/%d",num,high - num);
	} 
} 

第二次水过去了,后面的就难了。。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值