2019年华科计算机学院机试题
pro01,梅森素数
#include <stdio.h>
#include <stdlib.h>
#define MAXN 100+5
#define LL_MAX ((1LL<<63)-1)
#define ll long long
/**
1、梅森素数
题目要求:
梅森素数是由梅森数而来。所谓梅森数,是指形如2^p-1 的一类数,其中指数 p 是素数,常记为 Mp 。如果梅森数是素数,就称为梅森素数。
题目要求是,输入一个长整型数,然后输出比该数字小的梅森素数
*/
// wiki:https://zh.wikipedia.org/wiki/%E6%A2%85%E6%A3%AE%E7%B4%A0%E6%95%B0
///Miller-Rabbin算法的复杂度与s有关 2^(-s)为出错率
const int s=50;
ll pow_mod(ll a,ll b,ll mod) {
ll ans=1;
while(b) {
if (b&1)
ans=ans*a%mod;
a = a*a%mod;
b >>= 1;
}
return ans;
}
int MRT(ll n) {
if(n == 2)
return 1;///2的时候 特判
for(ll i=1; i <= s; i++) {
ll tmp = rand()%(n-1)+1;
if(pow_mod(tmp,n-1,n) != 1)
return 0;///非素数
}
return 1;///素数
}
/// 六素数法
int is_prime(ll n) {
if(n <= 3)
return n>1;
if(n%3 ==0 || n%2 == 0)
return 0;
for(int i=5; i*i<=n; i++)
if(n % i == 0 || n % (i+2) == 0)
return 0;
return 1;
}
/** 这里只是拓展下知识面... 可忽略..
ll S[10], res[MAXN]; /// 注意long long的长度
/// 卢卡斯-莱默检验法(目前针对梅森数判断的最快方法)
int lucas_lerhm_pest() {
S[0]=4;
int i, cnt=0;
res[cnt++] = 3;///M2特判, 后面使用卢卡斯-莱默检验法
for(i=1; i<6; i++) {
S[i] = S[i-1]*S[i-1] - 2;
}
ll x=2, j=2;
while(x < LL_MAX && j<7) {
x = (1<<j) - 1;
if(S[j-2] % x == 0) {
res[cnt++] = x;
}
j++;
}
for(i=0; i<cnt; i++) {
printf("%d ", res[i]);
}
printf("\n");
}
*/
int main() {
ll n;
while(~scanf("%lld", &n)) {
ll x=2, j=2;
while(x <= n) {
x = (1LL<<j)-1;
if(is_prime(x)) {
printf("%d ", x);
}
j++;
}
puts("");
}
return 0;
}
pro02,文件处理(已补充)
//第二题 文件操作题
// 将第一题的源代码保存为abc.c文件,并且要求abc.c文件中有相当数量的注释,包括//和/*……*/两种形式的注释
//(1)读取abc文件的内容,将其显示在控制台上,并为每行代码增加一个符号。(10)
//(2)使源代码中的//类型的注释内容不显示在控制台中。(10)
//(3)使源代码中的/*……*/类型的注释内容不显示在控制台中。(10)
/**
此题代码参考https://github.com/RaoXuntian/HUST.CS/blob/master/2019%E5%8D%8E%E7%A7%91%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%80%83%E7%A0%94%E6%9C%BA%E8%AF%95%E9%A2%98%E7%9B%AE/abc.c
原代码没有考虑 /*……*/内部嵌套 单行注释//,在此基础上进一步考虑了代码头部有注释的情况,但是还没有解决嵌套注释的情形。
*/
#include <stdio.h>
#include <stdlib.h>
#define MAXN 10000+5
#define LL_MAX ((1LL<<63)-1)
#define ll long long
#define mem(a, n) memset(a, n, sizeof(a))
char buf[MAXN];
int flag = 1, line = 1, flag2 = 1;
void judge(int i) {
if (buf[i+1]=='/' && buf[i+2]=='/') { //消除行注释
flag = 0;
}
if(buf[i+1]=='\n' && flag == 0) { //
flag = 1;
}
if(buf[i+1]=='/' && buf[i+2]=='*') { //消除快注释
flag = -1;
// flag2 = -1;
}
if((buf[i-2]=='*' && buf[i-1]=='/') && (flag==-1)) {
flag = 1;
// flag2 = 1;
}
}
/*
void judge(int i) {
if(buf[i+1] == '/' && buf[i+2] == '/') {
// 消除单行注释
flag = 0;
}
if(buf[i+1]=='\n' && flag == 0) { // 单行注释后的
if(flag2 == 0)
flag = 2;
else
flag = 1;
}
if(buf[i+1] == '/' && buf[i+2] == '*') {
//消除多行注释
flag2 = 0;
}
if((buf[i-2]=='*'&&buf[i-1] == '/') && flag2 == 0 ) {
flag2 = 1;
}
}*/
int main() {
FILE *fp;
if ((fp=fopen("abc.c","r")) == NULL) {
perror("打开文件时发生错误");
exit(0);
}
for (int i = 0; i < MAXN; i++) {
buf[i] = fgetc(fp); //从指定的流 stream 获取下一个字符(一个无符号字符),并把位置标识符往前移动
if (buf[i]==EOF) {
break;
}
}
printf("%d ", line++);
judge(-1); //为了文件头部是否有注释的特判
for (int i = 0; buf[i] != EOF; i++) { //逐个字符处理
if (flag == 1 ) {
printf("%c", buf[i]);
} else if(flag!=1 && buf[i]=='\n') { //换行符
printf("%c", buf[i]);
}
if(buf[i]=='\n') { //输出行号
printf("%d ", line++);
}
judge(i);
}
printf("\n");
return 0;
}
pro03,字符串的操作
#include <stdio.h>
#include <stdlib.h>
#define MAXN 100+5
#define LL_MAX ((1LL<<63)-1)
#define ll long long
/**
3、字符串的操作
题目要求:
要求输入一个由字母构成的字符串,然后将每位字母后面两位的字母输出,让字母
形成一个环。就比如,输入的是 aBX ,输出的是 cDZ, 然后对每一位字符进行奇校
验,输出奇校验的 8 位二进制数,然后将奇校验的二进制数转换为十进制输出。
*/
void solve(char *str) {
int i, biNum[8];
for(i=0; str[i]; i++) {
int num = str[i], cnt=8;
while(num) {// 转换二进制
biNum[--cnt] = num%2;
num /= 2;
}
while(cnt>0) {///补0
biNum[--cnt] = 0;
}
int j, times=0;
for(j=0; j<8; j++) {
if(biNum[j] == 1) times++;
}
if(times % 2 == 0) ///奇校验
biNum[0]=1;
int ans=0;
for(j=0; j<8; j++) {
ans=ans*2+biNum[j];
printf("%d", biNum[j]);
}
printf(" %d\n",ans);
}
}
int main() {
char mes[MAXN];
while(~scanf("%s", mes)) {
int i;
for(i=0; mes[i]; i++) {
if(mes[i]>='A'&&mes[i]<='Z') {
mes[i] = (mes[i]-65+2)%26+65;
} else if(mes[i]>='a' && mes[i]<='z') {
mes[i] = (mes[i]-97+2)%26+97;
}
}
puts(mes);
solve(mes);
}
return 0;
}
2019年华科软院机试题
pro01, 奇数魔方阵
#include <stdio.h>
#include <stdlib.h>
#define MAXN 1000+5
#define LL_MAX ((1LL<<63)-1)
#define ll long long
#define mem(a, n) memset(a, n, sizeof(a))
/**
1. 魔方阵,古代又称“纵横图”,是指组成元素为自然数 1 、 2 n 的平方的 n × n 的
方阵,其中 每个元素值都不相等,且每行、每列以及主、副对角线上各 n 个元素之
和都相等。阶数大于等于 3 。
如 3 × 3 的魔方阵:
8 1 6
3 5 7
4 9 2
奇数魔方阵的排列规律如下:
(1) 将 1 放在第一行中间一列;
(2) 从 2 开始直到 n × n 止各数依次按下列规则存放;每一个数存放的行比前一
个数的行数减 1 ,列数加 1 (例如上面的三阶魔方阵 5 在 4 的上一行后一列);
(3)如果上一个数的行数为如果上一个数的行数为11,则下一个数的行数为,则下一个数的行数为n(n(指最下一行指最下一行););例如例如11在在第一行,则第一行,则22应放在最下一行,列数同样加应放在最下一行,列数同样加11;;
(4))当上一个数的列数为当上一个数的列数为nn时,下一个数的列数应为时,下一个数的列数应为11,行数减去,行数减去11。例如。例如22在在第第33行最后一列,则行最后一列,则33应放在第二行第一列;应放在第二行第一列;
(5)如果按上面规则确定的位置上已有数,或上一个数是第一行第如果按上面规则确定的位置上已有数,或上一个数是第一行第nn列时,则列时,则把下一个数放在上一个数的下面。例如按上面的规定,把下一个数放在上一个数的下面。例如按上面的规定,44应该放在第应该放在第11行第行第22列,列,但该位置已经被占据,所以但该位置已经被占据,所以44就放在就放在33的下面;的下面;
输入格式:
输入魔方阵的阶数(阶数大于等于
3 的奇数阵)
输出格式:
输出魔方阵
输入样例:
3
输出样例:
8 1 6
3 5 7
4 9 2
2.
*/
int matrix[MAXN][MAXN];
void solve(int n) {
mem(matrix, 0);
matrix[0][n/2] = 1; //条件(1)
int preRow=0, preCol=n/2, nextRow, nextCol;
int num=2; //当前需要放置的数字
while(num<=n*n) {
// 条件(2) (3) (4)
nextRow = (preRow-1+n) % n;
nextCol = (preCol+1+n) % n;
if(matrix[nextRow][nextCol]!=0 || (preRow==0 && preCol==n-1)) {//(5)
nextRow=preRow+1;
nextCol=preCol;
}
matrix[nextRow][nextCol] = num++;
preRow = nextRow, preCol = nextCol;
}
int i,j;
for(i=0; i<n; i++) {
for(j=0; j<n; j++) {
printf("%5d ", matrix[i][j]);
}
puts("");
}
puts("");
}
int main() {
int n;
while(~scanf("%d", &n)) {
solve(n);
}
return 0;
}
pro02,单词个数统计(含‘,’判断)
#include <stdio.h>
#include <stdlib.h>
#define MAXN 1000+5
#define LL_MAX ((1LL<<63)-1)
#define ll long long
#define mem(a, n) memset(a, n, sizeof(a))
/**
2.从键盘输入一行字符,长度小于 1000 ,统计其中单词的个数,个单词以空格分
隔,且空格数可以是多个。
输入一行句子,仅有空格和英文字母构成。
输入格式:
输入只有一行句子。仅有空格和英文字母构成。(如含有逗号或者其他符号,即添
加一个 if 即可,如果逗号连接在两个单词之间,在 if 中统计逗号的数量,输出时
加上即可(默认不出现两个逗号之间只存在一个单词的情况和逗号单独出现的情
况))
输出格式:
单词的个数
输入样例:
To be or not to be This is a question
输出样例:
10
*/
// 这里代码把,当作一个单词了
char str[MAXN];
int main() {
freopen("dataIn.txt", "r", stdin);
while(gets(str)!=NULL) {
int num=0,i ;
for(i=0; str[i]; ) {
if(str[i]==' '){
i++;
continue;
}
if(str[i]==',') {
while(str[i++]==',') ;
num++;
continue;
}
while((str[i]>='A' && str[i]<='Z') || (str[i]>='a'&&str[i]<='z')) {
i++;
}
num++;
}
printf("%d\n", num);
}
return 0;
}