PTA-暑期学校-Day6-C语言
1 A乘以B
给定两个绝对值不超过100的整数A和B,输出A乘以B的值。
要求:
- 输入格式:
输入在第一行给出两个整数A和B(-100<=A,B<=100),数字间以空格分隔。 - 输出格式:
在一行中输出A乘以B的值。 - 输入样例:
-8 13
- 输出样例:
-104
代码长度限制 16KB
时间限制 400ms
内存限制 64MB
代码:
#include<stdio.h>
#include<string.h>
int main()
{
int A,B;
scanf("%d %d",&A,&B);
int C;
C=A*B;
printf("%d",C);
return 0;
}
2 比较大小
要求将输入的任意3个整数从小到大输出。
要求:
- 输入格式:
输入在一行中给出3个整数,其间以空格分隔。 - 输出格式:
在一行中将3个整数从小到大输出,其间以“->”相连。 - 输入样例:
4 2 8
- 输出样例:
2->4->8
代码长度限制 16KB
时间限制 400ms
内存限制 64MB
代码:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
if(x>y&&y>z)
printf("%d->%d->%d",z,y,x);
if(x>z&&z>y)
printf("%d->%d->%d",y,z,x);
if(y>z&&z>x)
printf("%d->%d->%d",x,z,y);
if(y>x&&x>z)
printf("%d->%d->%d",z,x,y);
if(z>x&&x>y)
printf("%d->%d->%d",y,x,z);
if(z>y&&y>x)
printf("%d->%d->%d",x,y,z);
if(x==y&&x<z)
printf("%d->%d->%d",x,y,z);
if(x==z&&x<y)
printf("%d->%d->%d",x,z,y);
if(y==z&&y<x)
printf("%d->%d->%d",z,y,x);
if(x==y&&y==z)
printf("%d->%d->%d",x,y,z);
return 0;
}
3 求组合数
编写程序,根据公式如下算出从n个不同元素中取出m个元素(m<=n)的组合数。
建议定义和调用函数fact(n)计算n!,其中n的类型是int,函数类型是double。
要求:
- 输入格式:
输入在一行中给出两个正整数m和n(m<=n),以空格分隔。 - 输出格式:
按照格式“result = 组合数计算结果”输出。题目保证结果在double类型范围内。 - 输入样例:
2 7
- 输出样例:
result = 21
代码长度限制 16KB
时间限制 400ms
内存限制 64MB
代码:
#include<stdio.h>
#include<stdlib.h>
double fact(int x)
{
double y=1.0;
for(int i=2;i<=x;i++)
{
y=y*i;
}
return y;
}
int main()
{
int m,n;
scanf("%d %d",&m,&n);
double result;
result=fact(n)/(fact(m)*fact(n-m));
printf("result = %.0f\n",result);
return 0;
}
4 求奇数分之一序列前N项和
编写程序,计算序列 1 + 1/3 + 1/5 + … 的前N项之和。
要求:
- 输入格式:
输入在一行中给出一个正整数N。 - 输出格式:
在一行中按照“sum = S”的格式输出部分和的值S,精确到小数点后6位。题目保证计算结果不超过双精度范围。 - 输入样例:
23
- 输出样例:
sum = 2.549541
代码长度限制 16KB
时间限制 400ms
内存限制 64MB
代码:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int N;
scanf("%d",&N);
double S;
int s=1;
for(int i=1;s<=N;i=i+2)
{
S=S+1.0/i;
s++;
}
printf("sum = %.6lf",S);
return 0;
}
5 输出闰年
输出21世纪中截止某个年份以来的所有闰年年份。注意:闰年的判别条件是该年年份能被4整除但不能被100整除、或者能被400整除。
要求:
- 输入格式:
输入在一行中给出21世纪的某个截止年份。 - 输出格式:
逐行输出满足条件的所有闰年年份,即每个年份占一行。输入若非21世纪的年份则输出"Invalid year!"。若不存在任何闰年,则输出“None”。 - 输入样例1:
2048
- 输出样例1:
2004
2008
2012
2016
2020
2024
2028
2032
2036
2040
2044
2048
- 输入样例2:
2000
- 输出样例2:
Invalid year!
代码长度限制 16KB
时间限制 400ms
内存限制 64MB
代码:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main()
{
int y;
scanf("%d",&y);
if(y<=2000||y>2100)
printf("Invalid year!\n");
else
{
int count=0;
for(int i=2001;i<=y;i++)
{
if(i%4==0&&i%100!=0||i%400==0)
{
printf("%d\n",i);
count++;
}
}
if(count==0)
printf("None");
}
return 0;
}
6 猴子吃桃问题
一只猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个;第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半加一个。到第N天早上想再吃时,见只剩下一个桃子了。问:第一天共摘了多少个桃子?
要求:
- 输入格式:
输入在一行中给出正整数N(1<N≤10)。 - 输出格式:
在一行中输出第一天共摘了多少个桃子。 - 输入样例:
3
- 输出样例:
10
代码长度限制 16KB
时间限制 400ms
内存限制 64MB
代码:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int N;
scanf("%d",&N);
int sum=1,d=1;
while(d<N)
{
sum=2*(sum+1);
d++;
}
printf("%d",sum);
return 0;
}
7 最长连续递增子序列
给定一个顺序存储的线性表,请设计一个算法查找该线性表中最长的连续递增子序列。例如,(1,9,2,5,7,3,4,6,8,0)中最长的递增子序列为(3,4,6,8)。
要求:
- 输入格式:
输入第1行给出正整数n(≤105);第2行给出n个整数,其间以空格分隔。 - 输出格式:
在一行中输出第一次出现的最长连续递增子序列,数字之间用空格分隔,序列结尾不能有多余空格。 - 输入样例:
15
1 9 2 5 7 3 4 6 8 0 11 15 17 17 10
- 输出样例:
3 4 6 8
代码长度限制 16KB
时间限制 400ms
内存限制 64MB
代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
int n;
scanf("%d",&n);
int i,a[100000];
int left=0,right=0,len=0,mlen=0,l=0;
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<n;i++)///令len等于整个序列长度;left最左侧的一数据;right序列最右侧的数据
{
len++;
if(len>mlen)
{
mlen=len;
left=l;
right=i;
}
if(a[i]>=a[i+1])///当右侧数据小或等于左侧数据,序列结束,len归零,l重新计数
{
len=0;
l=i+1;
}
}
for(i=left;i<right;i++)
printf("%d ",a[i]);
printf("%d",a[i]);
return 0;
}
8 求前缀表达式的值
算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。前缀表达式指二元运算符位于两个运算数之前,例如2+3*(7-4)+8/4的前缀表达式是:+ + 2 * 3 - 7 4 / 8 4。请设计程序计算前缀表达式的结果值。
要求:
- 输入格式:
输入在一行内给出不超过30个字符的前缀表达式,只包含 + 、 -、*、/ 以及运算数,不同对象(运算数、运算符号)之间以空格分隔。 - 输出格式:
输出前缀表达式的运算结果,保留小数点后1位,或错误信息ERROR。 - 输入样例:
++ 2 * 3 - 7 4 / 8 4
- 输出样例:
13.0
代码长度限制 16KB
时间限制 400ms
内存限制 64MB
代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
double exp()
{
char a[10]; //存储第一个非空格字符
scanf("%s",a);
if( !a[1])
{
//a[1]为空只有一位
switch( a[0])
{
case '+' :
return exp()+exp();
case '-' :
return exp()-exp();
case '*' :
return exp()*exp();
case '/' :
{
double fenzi = exp();
double fenmu = exp();
if(fenmu !=0) return fenzi/fenmu;
else
{
printf("ERROR"); //分母为0
exit(0); //程序结束
}
}
default :
return atof(a); //字符串转换为浮点数
}
}
else
{
if( a[0]=='-' || a[0]=='+')
{
char flag = a[0]; //记录符号
int i =0 ;
while(a[i])
{
a[i] = a[i+1];
i++;
}
if(flag=='-')
return 0-atof(a);
else return atof(a);
}
else return atof(a);
}
}
int main()
{
printf("%.1f",exp());
return 0;
}
9 打印学生选课清单
假设全校有最多40000名学生和最多2500门课程。现给出每门课的选课学生名单,要求输出每个前来查询的学生的选课清单。注意:每门课程的选课人数不可超过 200 人。
要求:
- 输入格式:
输入的第一行是两个正整数:N(≤40000),为前来查询课表的学生总数;K(≤2500),为总课程数。此后顺序给出课程1到K的选课学生名单。格式为:对每一门课,首先在一行中输出课程编号(简单起见,课程从1到K编号)和选课学生总数(之间用空格分隔),之后在第二行给出学生名单,相邻两个学生名字用1个空格分隔。学生姓名由3个大写英文字母+1位数字组成。选课信息之后,在一行内给出了N个前来查询课表的学生的名字,相邻两个学生名字用1个空格分隔。 - 输出格式:
对每位前来查询课表的学生,首先输出其名字,随后在同一行中输出一个正整数C,代表该生所选的课程门数,随后按递增顺序输出C个课程的编号。相邻数据用1个空格分隔,注意行末不能输出多余空格。 - 输入样例:
10 5
1 4
ANN0 BOB5 JAY9 LOR6
2 7
ANN0 BOB5 FRA8 JAY9 JOE4 KAT3 LOR6
3 1
BOB5
4 7
BOB5 DON2 FRA8 JAY9 KAT3 LOR6 ZOE1
5 9
AMY7 ANN0 BOB5 DON2 FRA8 JAY9 KAT3 LOR6 ZOE1
ZOE1 ANN0 BOB5 JOE4 JAY9 FRA8 DON2 AMY7 KAT3 LOR6
- 输出样例:
ZOE1 2 4 5
ANN0 3 1 2 5
BOB5 5 1 2 3 4 5
JOE4 1 2
JAY9 4 1 2 4 5
FRA8 3 2 4 5
DON2 2 4 5
AMY7 1 5
KAT3 3 2 4 5
LOR6 4 1 2 4 5
代码长度限制 16KB
时间限制 400ms
内存限制 64MB
代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
const int N=26*26*26*10+1;
typedef struct list
{
int lid;
struct list* next;
} L;
typedef struct table
{
L* head;
L* tail;
int cnt;
} T;
T* st[26*26*26*10+1];
int ID(char s[])
{
return (int)((s[3]-'0')+(s[2]-'A')*10+(s[1]-'A')*26*10+(s[0]-'A')*26*26*10);
}
int main()
{
for(int i=0; i<N; i++)
{
T* t=(T*)malloc(sizeof(T));
t->head=(L*)malloc(sizeof(L));
t->head->next=NULL;
t->cnt=0;
t->tail=t->head;
st[i]=t;
}
int n,k;//查询课表的学生总数,总课程数
scanf("%d%d",&n,&k);
for(int i=1; i<=k; i++)
{
int cid,stnum;//课程编号,选课学生总数
scanf("%d%d",&cid,&stnum);
for(int j=0; j<stnum; j++)
{
char sid[5];
scanf("%s",sid);
int id=ID(sid);
L* t=(L*)malloc(sizeof(L));
t->lid=cid;
t->next=NULL;
st[id]->tail->next=t;
st[id]->tail=st[id]->tail->next;
(st[id]->cnt)++;
}
}
for(int i=0; i<n; i++)
{
char sid[5];
scanf("%s",sid);
printf("%s",sid);
int id=ID(sid);
printf(" %d",st[id]->cnt);
L* p=st[id]->head->next;
//桶排序
int* ck=(int*)malloc(sizeof(int)*(k+1));
for(int i=1; i<=k; i++)
{
ck[i]=0;
}
while(p)
{
ck[p->lid]=1;
p=p->next;
}
for(int i=1; i<=k; i++)
{
if(ck[i]==1)
{
printf(" %d",i);
}
}
free(ck);//释放内存
printf("\n");
}
return 0;
}
10 修理牧场
农夫要修理牧场的一段栅栏,他测量了栅栏,发现需要N块木头,每块木头长度为整数 Li 个长度单位,于是他购买了一条很长的、能锯成N块的木头,即该木头的长度是 Li 的总和。
但是农夫自己没有锯子,请人锯木的酬金跟这段木头的长度成正比。为简单起见,不妨就设酬金等于所锯木头的长度。例如,要将长度为20的木头锯成长度为8、7和5的三段,第一次锯木头花费20,将木头锯成12和8;第二次锯木头花费12,将长度为12的木头锯成7和5,总花费为32。如果第一次将木头锯成15和5,则第二次锯木头花费15,总花费为35(大于32)。
请编写程序帮助农夫计算将木头锯成N块的最少花费。
要求:
- 输入格式:
输入首先给出正整数N(≤104 ),表示要将木头锯成N块。第二行给出N个正整数(≤50),表示每段木块的长度。 - 输出格式:
输出一个整数,即将木头锯成N块的最少花费 - 输入样例:
8
4 5 1 2 1 3 1 1
- 输出样例:
49
代码长度限制 16KB
时间限制 400ms
内存限制 64MB
代码:
#include<stdio.h>
#include<stdlib.h>
// 自定义一个将数组从小到大排序的方法
void sort(int *a,int m){
int i=0,j=0,t;
for(i=0;i<m;i++){
for(j=0;j<i;j++){
if(a[j]<a[i]){
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
}
}
int main()
{
int N,costsum=0,i,index;
scanf("%d",&N);
int *a=malloc(sizeof(int)*N);
for(i=0;i<N;i++)
scanf("%d",&a[i]);
// 输入完毕,排列数组
sort(a,N);
int sum=0;
for(i=0;i<N-1;i++){
// 找出前两个数(即为数组最小的两个数)相加
sum=a[i]+a[i+1];
// 花费求和
costsum=costsum+sum;
// 比较之前两个最小数的和与数组中各个元素的大小,找到合适的位置,将其放入数组
// 从第三个数开始,前两个最小数拿出去求和了
for(index=i+2;index<N;index++)
{
// 前两个数的和大于当前值,继续往后找
if(sum>a[index])
a[index-1]=a[index];
else
{
// 不大于就找到位置,结束循环
a[index-1]=sum;
break;
}
}
// 比到最后一个数还没找到,就把sum加到最后
if(index==N)
a[N-1]=sum;
}
printf("%d\n",costsum);
return 0;
}