高级(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。
公式贴不到代码段里面啊
一道坑题,A完之后我才知道有个%e的输出格式。主要我也不知道测试数据是啥,本地测了下%e跟第一次代码跑的结果有的不一样,然而都A了,也是很迷。
开始没有思路然后就硬算好了,我这里的思路在计算过程还是看得出来的,先算,再乘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);
}
}
第二次水过去了,后面的就难了。。。。