虽然没有选C2这门课程,不过还是去听下课顺便完成作业吧,反正这学期课挺少的。
小题就算了不写了。
子串逆置
【问题描述】
输入两行字符串s和t(s和t可以含空格,length(t)≤length(s)≤50),将s串中首次与t匹配的子串逆置,并将处理后的s串输出。
【输入形式】
输入文件为当前目录下的invertsub.in。 文件中有两行字符串s和t,分别以换行符作为结束符,其中换行符可能是Linux下的换行符,也可能是Windows下的换行符。
【输出形式】
输出文件为当前目录下的invertsub.out。 输出文件只有一行,包含一个串,为要求的输出结果。行末要输出一个回车符。
【输入样例】
helloworld
llowor
【输出样例】
herowollld
【时间限制】
1s
【空间限制】
65536KB
【上传文件】
上传c语言源程序,文件名为invertsub.c。
在本地测试的时候文本最后没加换行debug了好久= =,逆置还是挺基础和简单的。不过这题用到strstr返回的是出现的地址,所以用指针写。
#include<stdio.h>
#include<string.h>
void rev(char *first, char *last)
{
int temp;
while (first < last)
{
temp = *first;
*first = *last;
*last = temp;
first++; last--;
}
}
int main()
{
char s[52], t[52], *p;
FILE *in, *out;
in = fopen("invertsub.in", "r");
out = fopen("invertsub.out", "w");
fgets(s, 52, in); fgets(t, 52, in);
s[strlen(s) - 1] = '\0';
t[strlen(t) - 1] = '\0';
if ((p = strstr(s, t)) != NULL)
rev(p, p + strlen(t) - 1);
fprintf(out, "%s\n", s);
fclose(in); fclose(out);
}
区间
【问题描述】
给定n个闭区间[ai, bi](1 <= i <= n),这些区间的并可以表示为一些不相交的闭区间的并。要求在这些表示方式中找出包含不相交区间数目最少的方案。
【输入形式】
输入文件为当前目录下的prz.in。 该文件包含n行(3 <= n <= 50000),每行各包括两个以空格分隔的整数ai 和 bi,表示一个区间[ai, bi](1 <= ai <= bi <= 1000000)。
【输出形式】
输出文件为当前目录下的prz.out。 该文件内容为计算出来的不相交的区间。每一行都是对一个区间的描述,包括两个以空格分开的整数,分别为区间的下界和上界。 输出时将各区间按照升序排列输出。这里说两个区间[a, b]和[c, d]是按照升序排列的,是指a <= b < c <= d。
【输入样例】
5 6 1 4 10 10 6 9 8 10
【输出样例】
1 4 5 10
【时间限制】
1s
【空间限制】
65536KB
【上传文件】
上传c语言源程序,文件名为prz.c。
这次里面算是最难的一道了吧。分析步骤如下:
(1)首先根据区间的下界排序,这里如果用复杂度的排序(我用的选择排序)好像会超时,所以用快排吧(我这是手写的快排,用自带的qsort应该会比较快)
(2)逐个比对,如果区间能够相交则合并,记录最大的上界。如果一个区间的下界比之前区间的上界还大,说明这两个区间必定不相交,输出之前的区间。
#include<stdio.h>
struct prz {
int high;
int low;
}p[50007];
void qsort(struct prz p[], int left, int right);
void print(struct prz p[], int n, FILE *out);
void swap(struct prz p[], int i, int j);
int main()
{
FILE *in, *out;
in = fopen("prz.in", "r");
out = fopen("prz.out", "w");
int i;
int cnt = 0;
while ((fscanf(in, "%d%d", &p[cnt].low, &p[cnt].high)) != EOF)
{
cnt++;
}
qsort(p, 0, cnt - 1);
print(p, cnt, out);
fclose(in); fclose(out);
}
void qsort(struct prz p[], int left, int right)
{
struct prz temp;
int i, j;
if (left < right) {
j = left;
for (i = left + 1; i <= right; i++) {
if (p[i].low < p[left].low)
swap(p, i, ++j);
}
swap(p, j, left);
qsort(p, left, j - 1);
qsort(p, j + 1, right);
}
}
void print(struct prz p[], int n, FILE *out)
{
int last = 0;
int i;
fprintf(out, "%d ", p[0].low);
for (i = 1; i < n; i++)
{
if (p[i].low > p[last].high)
{
fprintf(out, "%d\n%d ", p[last].high, p[i].low);
last = i;
}
else if (p[i].high > p[last].high)
last = i;
}
fprintf(out, "%d\n", p[last].high);
}
void swap(struct prz p[], int i, int j)
{
struct prz temp = p[i];
p[i] = p[j];
p[j] = temp;
}
兑换硬币
【问题描述】
写一个程序,从标准输入上读入一个正整数N(1 <= N <=1000),计算出N元人民币兑换成1分、2分和5分的硬币,有多少种可能的组合。将结果以整数的方式输出到标准输出上,占一行。
【输入形式】
正整数N。(1 <= N <=1000)
【输出形式】
整数。
【输入样例】
1
【输出样例】
541
【时间限制】
1s
【空间限制】
65536KB
【上传文件】
上传c语言源程序,文件名为nickle.c。
水题。暴力做会超时。
事实上如果遍历5分硬币的数量,根据剩余金额可以直接算出来有几种组合,因为只需要数2分硬币有几种情况,剩下的1分都能补足。我稍微化简了一下所以看着不是很清晰,凑合吧。
#include<stdio.h>
int count(int n)
{
int i;
int cnt = 0;
for (i = 0; i <= n * 20; i++)
{
cnt += (n * 100 - i * 5) / 2 + 1;
}
return cnt;
}
int main()
{
int n;
scanf("%d", &n);
printf("%d", count(n));
}
实数格式识别
【问题描述】
合法的实数书写格式分一般格式和科学格式两种。分别描述如下:
一般格式为常见的书写格式,分为整数部分和小数部分两部分,中间分用小数点.分隔。整数部分最开始可能含有正号或负号,之后为不含前导零的数字串;小数部分是由0-9十种字符组成的任意长的字符串。当小数部分为0时,小数部分和小数点可以省略。
科学格式由系数部分和指数部分两部分组成,中间用英文字母E分隔。系数部分为实数书写的一般格式;指数部分为可带有正负号数字串。
例如,+2、-1.56为一般格式的实数,而6.2E-2、-9E8为科学格式的实数。
只有小数点而没有小数部分的书写格式为不合法,例如,23.,23.E16均为不合法的实数书写格式。
编程分析哪些数的书写是正确的,是用哪种方式书写的。
【输入形式】
输入文件为当前目录下的real.in。 该文件包含一个字符串(长度不超过20个字符),以回车符结束,表示一个数据(无多余空格)。
【输出形式】
输出文件为当前目录下的real.out。 该文件有一行。如果输入数据的书写是非法的,输出Wrong;如果输入数据是用一般格式书写的,输出“Format1”;如果该数据是用科学格式书写的,输出“Format2”。输出的末尾均要以一个回车符作为结束。
【输入样例1】
+1.23
【输出样例1】
Format1
【输入样例2】
-5.1.1
【输出样例2】
Wrong
【输入样例3】
-5.1E-2
【输出样例3】
Format2
【时间限制】
1s
【空间限制】
65536KB
【上传文件】
上传c语言源程序,文件名为real.c。
不难但是很繁琐的一道题,思路可以用状态机来完成,但是我怕出错就没这么写。一开始写了一个超级繁琐的版本后来改成下面这个版本。
普通格式与科学格式的特征区别:E
<普通格式> E [<符号>] <整数>
如果有E我们就用科学格式来判别,E前面是否为<普通格式>,后面是否为[符号]+整数。如果没有E我们就判断是否为普通格式。
普通格式的两种类型:是否有小数点
[<符号>]<整数> . <整数>
[<符号>]<整数>
所以我们根据有无小数点,判断小数点前面和后面是否分别满足条件即可。
#include<stdio.h>
#include<string.h>
#include<stdbool.h>
#include<ctype.h>
void judge(char s[], int length, FILE *out);
bool judgeDec(char s[], int first, int last);
bool judgeInt(char s[], int first, int last);
bool judgeExp(char s[], int fisrt, int last, int eindex);
int main()
{
char s[22];
FILE *in, *out;
in = fopen("real.in", "r");
out = fopen("real.out", "w");
fgets(s, 22, in);
s[strlen(s) - 1] = '\0';
int length = strlen(s);
judge(s, length, out);
close(in); close(out);
return 0;
}
void judge(char s[], int length, FILE *out)
{
int i;
for (i = 0; i < length; i++)
if (s[i] == 'E')
break;
if (i + 1 == length)
fprintf(out, "Wrong\n");
else if (i == length)
{
if (judgeDec(s, 0, length - 1))
fprintf(out, "Format1\n");
else
fprintf(out, "Wrong\n");
}
else
{
if (judgeExp(s, 0, length - 1, i))
fprintf(out, "Format2\n");
else
fprintf(out, "Wrong\n");
}
}
bool judgeDec(char s[], int first, int last)
{
int pindex;
int pflag = 0;
bool judge = false;
int i = (s[first] == '-' || s[first] == '+') ? first + 1 : first;
for (pindex = first; pindex <= last; pindex++)
if (s[pindex] == '.')
{
pflag++;
break;
}
if (!pflag)
judge = judgeInt(s, i, last);
else
judge = judgeInt(s, i, pindex - 1) && judgeInt(s, pindex + 1, last);
return judge;
}
bool judgeInt(char s[], int first, int last)
{
if (first > last)
return false;
while (isdigit(s[first]) && first <= last)
first++;
if (first == last + 1)
return true;
else
return false;
}
bool judgeExp(char s[], int first, int last, int eindex)
{
bool judge = false;
int i = (s[eindex + 1] == '-' || s[eindex + 1] == '+') ? eindex + 2 : eindex + 1;
judge = judgeDec(s, first, eindex - 1) && judgeInt(s, i, last);
return judge;
}
在judgeDec和judgeExp我没有对left<=right进行规约, 因为最终都是调用judgeInt,如果不满足还是会return false。
N!的分解
【问题描述】
将N!分解成素数幂的乘积。
【输入形式】
从标准输入读取一个整数N(1 <= N <= 30000)。
【输出形式】
结果打印到标准输出。 输出格式为:p1^k1*p2^k2…其中p1,p2…为质数且ki>1。当ki=1时只输出pi,ki=0的项不输出。分解式中的素数按从小到大输出。
【输入样例】
5
【输出样例】
2^3*3*5
【时间限制】
1s
【空间限制】
65536KB
【上传文件】
上传c语言源程序,文件名为decompose.c。
对2~N出现的每一个数,将其所有质因子加入质数表中记录出现次数。不过我没有记录用质数表而是直接用数组存,反正效果差不多= =
另外输出的时候特判一下就行了
#include<stdio.h>
#define MAXNUM 30001
int prime[MAXNUM] = { 0 };
void gen_factor(int n, int prime[]);
void print(int n, int prime[]);
int main()
{
int n;
scanf("%d", &n);
gen_factor(n, prime);
print(n, prime);
}
void gen_factor(int n, int prime[])
{
int i, j, temp;
for (i = 2; i <= n; i++)
{
temp = i;
for (j = 2; j <= temp; j++)
{
if (temp % j == 0)
{
prime[j] ++;
temp /= j;
j--;
}
}
}
}
void print(int n, int prime[])
{
int i, first = 1;
for (i = 2; i <= n; i++)
{
if (prime[i] == 1)
{
if (first)
{
first = 0;
printf("%d", i);
}
else
printf("*%d", i);
}
else if (prime[i] > 1)
{
if (first)
{
first = 0;
printf("%d^%d", i, prime[i]);
}
else
printf("*%d^%d", i, prime[i]);
}
}
}
好好学吧,这学期尽量坚持一件事。把C2的平时练习都写完然后写博客,看看能不能坚持这学期
2019.2.27更新:
C2实在是写不下去了,题目难度还是差不多有点难,但是输入实在太搞了,弃坑了