2015级计算机学院《程序设计基础(1)》(第一场)
Problem A: 花坛
Description
学校要修一些圆形的花坛,每个花坛外围铺一圈大理石的地面。现在知道花坛的内圆半径r米和大理石地面的外圆半径R米,求大理石地面的面积。
圆周率取3.14159。
Input
输入两个浮点数r和R。
Output
输出大理石地面的面积,精确到小数点后三位。
Sample Input
2 3
Sample Output
15.708
思路:送分的。
ac code:
#include<stdio.h>
int main()
{
double r,R;
scanf("%lf %lf",&r,&R);
printf("%.3lf",3.14159*(R*R-r*r));
return 0;
}
Problem B: 夏季促销
Description
商场夏季促销,购物399元(含)以上,95折;购物899元(含)以上,9折;购物2499元(含)以上,85折;购物4899元(含)以上,8折。并且不收取角分部分。
根据购物金额,确定用户实际需要支付的数目。
Input
输入客户购买若干物品的单价金额,均为正整数,至EOF结束。
Output
输出用户实际需要支出的数目,以元为单位,保留两位小数。
Sample Input
105
398
742
82
888
276
Sample Output
2241.00
思路:注意读题,将题目所述范围化为if-else语句块,注意题目中(含)的意思!
ac code:
#include<stdio.h>
int main()
{
int sum=0;
int e;
while(scanf("%d",&e)!=EOF){
sum+=e;
}
if(sum<399){
int ans=(int)(sum*1.0);
double all=sum*1.0-(sum*1.0-ans);
printf("%.2lf",all);
}else if(sum>=399&&sum<899){
int ans=(int)(sum*0.95);
double all=sum*0.95-(sum*0.95-ans);
printf("%.2lf",all);
}else if(sum>=899&&sum<2499){
int ans=(int)(sum*0.9);
double all=sum*0.9-(sum*0.9-ans);
printf("%.2lf",all);
}else if(sum>=2499&&sum<4899){
int ans=(int)(sum*0.85);
double all=sum*0.85-(sum*0.85-ans);
printf("%.2lf",all);
}else{
int ans=(int)(sum*0.8);
double all=sum*0.8-(sum*0.8-ans);
printf("%.2lf",all);
}
return 0;
}
Problem C: 鸡兔同笼
Description
鸡兔同笼是中国古代的数学名题之一。大约在1500年前,《孙子算经》中就记载了这个有趣的问题。书中是这样叙述的:“今有雉兔同笼,上有三十五头,下有九十四足,问雉兔各几何?”
一个笼子里关了鸡和兔子(鸡有2只脚,兔子有4只脚,没有例外)。已知鸡和兔的总头数为n,总腿数为m。输入n和m,依次输出鸡的数目和兔的数目。如果无解,则输出“no result”。
Input
首先输入一个正整数k<20,表示有k组测试数据。
每组测试输入正整数n和m(均小于1000),分别表示鸡兔的总头数及总腿数。
Output
每行依次输出鸡的数目和兔的数目,用一个空格分开。如果无解,则输出“no result”。
Sample Input
2
35 94
10 42
Sample Output
23 12
no result
思路: 先数学计算一下x(鸡数),y(兔数) y=(m-2n)/2;
x=(4n-m)/2;
注意x>=0,y>=0且要满足头数和腿数关系!
ac code:
#include<stdio.h>
int main()
{
int k;
scanf("%d",&k);
int n,m;
for(int i=0;i<k;i++){
scanf("%d %d",&n,&m);
int y=(m-2*n)/2;
int x=(4*n-m)/2;
if(x+y==n&&2*x+4*y==m&&x>=0&&y>=0){
printf("%d %d\n",x,y);
}else{
printf("no result\n");
}
}
return 0;
}
Problem D: 递归求和
Description
输入一组数字,用递归的方法求和。
Invalid Word(禁用单词)错误:在解决这个题目时,某些关键词是不允许被使用的。如果提交的程序中包含了下列的关键词之一,就会产生这个错误。
被禁用的关键字:循环语句for、while,甚至包括分支语句的switch、case、goto。
Input
第一行输入一个正整数k(k<1000),第二行为k个整数。
Output
输出这k个整数的和。
Sample Input
10
1 2 3 4 5 6 7 8 9 10
Sample Output
55
思路: 找好递归边界; 找好递归关系!
ac code:
#include<stdio.h>
int sum(int k){
int e;
if(k==1){
scanf("%d",&e);
return e;
}else{
scanf("%d",&e);
return e+sum(k-1);
}
}
int main()
{
int k;
scanf("%d",&k);
int ans=sum(k);
printf("%d",ans);
return 0;
}
Problem E: 歌德巴赫猜想的证明
Description
验证“每个不小于6的偶数都是两个奇素数之和”,输入一个不小于6的偶数n,找出两个奇素数,使它们的和为n。
Input
输入一个不小于6的偶数n,n<10000。
Output
找出两个奇素数,使它们的和为n。如果有多种答案,则每个答案占一行。注意:在输出时,第一个数不能大于第二个数。比如对于10,输出的答案只有3 + 7 = 10,没有7 + 3 =10。
每行的输出格式为:
a + b = c
a和b是满足条件的两个数,a<=b,c为输入的数。
多个答案的输出顺序,要按照第一个数递增的顺序输出。
Sample Input
20
Sample Output
3 + 17 = 20
7 + 13 = 20
思路:
注意1:不要超时,刚开始我写的外层循环是i<num,超时了,只对60%,外层循环改为i<=num/2就行
注意2:isPrime判断到sqrt(n)即可!
注意3:关于isPrime的优化有很多方案,这里不一一列举;
ac code:
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
int isPrime(int n)
{
for(int i=2;i<=sqrt(n);i++){
if(n%i==0)return 0;
}
return 1;
}
int main()
{
int num;
scanf("%d",&num);
for(int i=2;i<=num/2;i++){
for(int j=i;j<num;j++){
if(isPrime(i)&&isPrime(j)&&i+j==num){
printf("%d + %d = %d\n",i,j,num);
}
}
}
return 0;
}
Problem F: 登录密码验证 之二
Description
编写一个程序,模拟用户登录系统的密码验证过程。系统提供给用户的密码长度最长为20个字符,若密码输入错误可以再次输入。但为了保证用户密码安全,若连续输入密码错误超过5次就会锁定账号一段时间。
与此前不同的是,这次系统的密码验证是大小写无关的,也就是说同一个英文字母的大、小写视作相同字符。
Input
输入为若干个串,至EOF结束。输入的第一个串是用户的正确密码,后面的串为模拟用户登录时的输入的密码。
Output
每次输入错误的密码,输出一个“Wrong!”,若输入的密码为正确的,输出一个“Welcome!”,并结束密码测试。若前5次输入的密码都是错误的,则后面的输入中不管是否有正确的密码都输出“Out of limited!”。
Sample Input
ABCDEFG
123456 kkkkkkkk abcdefg
Sample Output
Wrong!
Wrong!
Welcome!
思路:
count<5进行判断;
count>=5直接输出:Out of limited!即可!
ac code:
#include<stdio.h>
#include<string.h>
int main()
{
char s[21];
scanf("%s",s);
for(int i=0;i<strlen(s);i++){
if(s[i]>='a'&&s[i]<='z'){
s[i]=s[i]+'A'-'a';
}
}
getchar();
int count=0;
char ss[21];
while(scanf("%s",ss)!=EOF){
for(int i=0;i<strlen(ss);i++){
if(ss[i]>='a'&&ss[i]<='z'){
ss[i]=ss[i]+'A'-'a';
}
}
if(count<5){
if(strcmp(s,ss)==0){
printf("Welcome!\n");
break;
}else{
printf("Wrong!\n");
}
}else{
printf("Out of limited!\n");
}
count++;
}
return 0;
}
Problem G: 数字的千位分隔
Description
把整数利用逗号进行千位分隔并输出。
Input
输入第一行是整数T(0<T<=50),表示接下来有T行,每行有一个整数,即为要利用逗号千位分隔的整数k,其中0<=k<=2^64-1。
Output
对应每一行数据输入,输出一行用逗号进行千位分隔的数字串。
Sample Input
3
12
123
12345
Sample Output
12
123
12,345
思路: 将数存在字符数组中; 再倒着存到另一个字符数组中,没count==3就加一个’,'隔开!
ac code:
#include<stdio.h>
#include<string.h>
int main()
{
int t;
scanf("%d",&t);
for(int i=0;i<t;i++){
char s[100];
getchar();
scanf("%s",s);
char ss[200];
int len=0;
int count=0;
for(int i=strlen(s)-1;i>=0;i--){
count++;
ss[len++]=s[i];
if(count==3){
count=0;
ss[len++]=',';
}
}
int high=len-1;
if(ss[high]==',')high--;
for(int i=high;i>=0;i--){
printf("%c",ss[i]);
}
printf("\n");
}
return 0;
}
Problem H: 用结构体来表示数组
Description
有如下结构体定义:
typedef struct {
int length;
int array[MAX_SIZE];
}ARR_TYPE;
其中,length表示数组中实际元素的个数,array[]用于存储length个数据,MAX_SIZE表示数组的最大长度。
要求编写如下两个函数:
- int input_arr(ARR_TYPE *arr);
用于按照样例给定的格式输入arr的内容。 - int output_arr(ARR_TYPE arr);
用于按照样例给定的格式输出arr中array的内容。
注意:提交时要提交相关的预处理命令(#include、#define等)以及结构体类型定义。
Input
输入只有一行,第一个数N表示后面会有N个整数,其中0<N<=10001,之后有N个整数,两两之间用空格隔开。
Output
输出只有一行,按照输入的顺序输出所有整数,两两之间用空格隔开。
Sample Input
10 1 2 3 4 5 6 7 8 9 10
Sample Output
1 2 3 4 5 6 7 8 9 10
思路:
注意1:对于结构体指针访问成员变量要用->
注意2:对于结构体访问成员变量要用.
ac code:
#include<stdio.h>
#define MAX_SIZE 20001
typedef struct
{
int length;
int array[MAX_SIZE];
}ARR_TYPE;
int input_arr(ARR_TYPE *arr)
{
scanf("%d",&arr->length);
for(int i=0;i<arr->length;i++){
scanf("%d",&arr->array[i]);
}
return 1;
}
int output_arr(ARR_TYPE arr)
{
for(int i=0;i<arr.length;i++){
printf("%d",arr.array[i]);
if(i<arr.length-1)printf(" ");
}
return 1;
}
int main()
{
ARR_TYPE arr;
input_arr(&arr);
output_arr(arr);
return 0;
}
Problem I: 求众数
Description
一组数据中出现次数最多的数值,叫众数,有时众数在一组数中有好几个。
Input
有多组测试数据。输入的第一行是整数T(0<T<=10),后接T组测试数据。
每组测试数据为一个整数n(1<n<1000),后接n个整数m(0<m<10000)。
Output
对应每组测试数据,输出出现最多的数的出现次数,同时输出出现最多的数,如果有多个数
出现次数都是最多,按从小到大顺序输出。
Sample Input
1
10 1 2 3 2 1 2 3 1 1 3
Sample Output
4 1
思路: 使用hashTable即可!
ac code:
#include<stdio.h>
int main()
{
int k;
scanf("%d",&k);
for(int i=0;i<k;i++){
int len1;
scanf("%d",&len1);
int e;
int a[10001]={
0};
for(int j=0;j<len1;j++){
scanf("%d",&e);
a[e]++;
}
int max=0;
for(int j=0;j<10000;j++){
if(a[j]>max)max=a[j];
}
int b[10000];
int len=0;
for(int j=0;j<10000;j++){
if(a[j]==max){
b[len++]=j;
}
}
printf("%d",max);
for(int j=0;j<len;j++){
printf(" %d",b[j]);
}
printf("\n");
}
return 0;
}
Problem J: 杨辉三角
Description
杨辉三角,又称贾宪三角形,帕斯卡三角形,是二项式系数在三角形中的一种几何排列。在欧洲,这个表叫做帕斯卡三角形。帕斯卡(1623----1662)是在1654年发现这一规律的,比杨辉要迟393年,比贾宪迟600年。
下图的表在我国南宋数学家杨辉1261年所著的《详解九章算法》一书里就出现了。其中下一层的每一项都是由上一层连边的两项相加得来。
Input
输入多组,每组一个正整数n<14,至EOF结束。
Output
每组输入对应输出n层的杨辉三角,每一项占4个字符,除了每行开始需要填充空格之外,任意两项之间不要有多余的空格。
两组输出之间用一个空行分开,最后一组数据之后不要添加空行。
输出详细格式见sample。
Sample Input
7
5
Sample Output
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
思路: 用二维数组去处理即可; 对于第一列全为1; 对角线全为1; 其余从第三行第二列开始每一个元素都等于它的上一行同一列元素加左上角元素!
ac code:
#include<stdio.h>
int main()
{
int n;
while(scanf("%d",&n)!=EOF){
int a[n+1][n+1];
for(int i=1;i<=n;i++){
a[i][1]=1;
a[i][i]=1;
}
for(int i=3;i<=n;i++){
for(int j=2;j<=i-1;j++){
a[i][j]=a[i-1][j]+a[i-1][j-1];
}
}
for(int i=1;i<=n;i++){
for(int k=0;k<2*n-2*i;k++){
printf(" ");
}
for(int k=1;k<=i;k++){
printf("%4d",a[i][k]);
}
printf("\n");
}
printf("\n");
}
return 0;
}
Problem K: 一共多少天
Description
安琪的18岁生日就要到了,她当然很开心。她想到了一个问题,是不是每个人从出生开始,到达18岁生日时所经过的天数都是一样的呢?似乎并不都是一样的。于是,她想编写一个程序来计算她和她的几个朋友从出生到达18岁生日所经过的总天数是多少?
Input
一个数T(T<=100),后面T行每行有一个日期,格式是YYYY-MM-DD。如安琪的生日是1988-03-07。日期均为正数,且合法。
Output
T行,每行一个数,表示此人从出生到18岁生日所经过的天数。如果这个人没有18岁生日,就输出-1。
Sample Input
1
1988-03-07
Sample Output
6574
思路: 对于生日是2.29号的人来说,很不幸,没18岁生日!
对于生日的月份>=3的,天数取决于最后一年是否是闰年;
对于生日的月份<3的,天数取决于第一年是否是闰年;
ac code:
#include<stdio.h>
int isOK(int year)
{
if(year%400==0||(year%4==0&&year%100!=0)){
return 1;
}
return 0;
}
int main()
{
int t;
scanf("%d",&t);
for(int i=0;i<t;i++){
int year,month,day;
scanf("%d-%d-%d",&year,&month,&day);
if(month==2&&day==29){
printf("-1\n");
continue;
}
int ans=0;
if(month>=3){
for(int i=1;i<=18;i++){
if(isOK(year+i))ans+=366;
else ans+=365;
}
}else{
for(int i=0;i<18;i++){
if(isOK(year+i))ans+=366;
else ans+=365;
}
}
printf("%d\n",ans);
}
return 0;
}