资源描述
题目 - 日历问题 1
题目 - 生日相同 3
题目 - 开关灯 5
题目 -出现次数超过一半的数 6
题目 - 谁考了第k名 8
题目 - 区间合并 9
题目 - 距离排序 12
题目 - 吃糖果问题 14
题目- 采药 16
题目- 辉辉的日程表 17
题目- 二进制加法 20
题目- 神奇的幻方 22
题目 - 试剂稀释 25
题目 - 日历问题
来源
Shanghai 2004 Preliminary
描述
在我们现在使用的日历中, 闰年被定义为能被4整除的年份,但是能被100整除而不能被400整除的年是例外,它们不是闰年。例如:1700, 1800, 1900 和 2100 不是闰年,而 1600, 2000 和 2400是闰年。 给定从公元2000年1月1日开始逝去得天数,你的任务是给出这一天是哪年哪月哪日星期几。
提示:2000年1月1日是周六
关于输入
输入包含若干行,每行包含一个正整数,表示从2000年1月1日开始逝去的天数。输入最后一行是−1, 不必处理。可以假设结果的年份不会超过9999。
关于输出
对每个测试样例,输出一行,该行包含对应的日期和星期几。格式为“YYYY-MM-DD DayOfWeek”, 其中 “DayOfWeek” 必须是下面中的一个: "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" and "Saturday“。
例子输入
1730
1740
1750
1751
-1
例子输出
2004-09-26 Sunday
2004-10-06 Wednesday
2004-10-16 Saturday
2004-10-17 Sunday
提交程序
#include <stdio.h>
int type(int);
char week[7][10] = {"Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"};
int year[2]= {365, 366};
int month[2][12] = {31, 28, 31, 30, 31, 30, 31, 31, 30,31, 30, 31,31, 29, 31, 30, 31, 30, 31, 31, 30,31, 30, 31};
int main(int argc, char* argv[])
{
int days, dayofweek;
int i = 0, j = 0;
while( scanf("%d", &days) && days != -1)
{
dayofweek = days % 7;
for( i = 2000; days >= year[type(i)]; i++)
days -= year[type(i)];
for( j = 0; days >= month[type(i)][j]; j++)
days -= month[type(i)][j];
printf("%d-%02d-%02d %s\n", i, j + 1, days + 1, week[dayofweek]);
}
return 0;
}
int type( int m)
{
if( m % 4 != 0 || ( m % 100 == 0 && m % 400 != 0 )) return 0;
else return 1;
}
题目 - 生日相同
来源
工学院计算概论07
描述
在一个有180人的大班级中,存在两个人生日相同的概率非常大,现给出每个学生的学号,出生月日。试找出所有生日相同的学生。
关于输入
第一行为整数n,表示有n个学生,n < 100。
此后每行包含一个字符串和两个整数,分别表示学生的学号(字符串长度小于10)和出生月(1 ≤ m ≤ 12)日(1 ≤ d ≤ 31)。
学号、月、日之间用一个空格分隔。
关于输出
对每组生日相同的学生,输出一行,
其中前两个数字表示月和日,后面跟着所有在当天出生的学生的学号,数字、学号之间都用一个空格分隔。
对所有的输出,要求按日期从前到后的顺序输出。
对生日相同的学号,按输入的顺序输出。
例子输入
6
00508192 3 2
00508153 4 5
00508172 3 2
00508023 4 5
00509122 4 5
00509146 4 6
例子输出
3 2 00508192 00508172
4 5 00508153 00508023 00509122
提示
注意,一个学生的生日不与其他任何学生的生日相同,则不输出该学生的记录。
字符串数组的输入输出使用示例:
char num[10];
scanf("%s",num);
printf("%s",num);
注意:字符串数组输入输出时不需要“&”
#include <stdio.h>
#include <string.h>
int main()
{
int y[100],r[100],t[100];
char xh[100][10],tmpxh[10],sc[100][10];
int n,i,k,j,tmpy,tmpr,tmpt,tx,h;
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%s %d %d",xh[i],&y[i],&r[i]);
t[i]=y[i]*31+r[i];
}
for(k=1;k<=n;k++){
for(i=0;i<n-k;i++){
if(t[i]>t[i+1]){
tmpy=y[i+1];
y[i+1]=y[i];
y[i]=tmpy;
tmpr=r[i+1];
r[i+1]=r[i];
r[i]=tmpr;
tmpt=t[i+1];
t[i+1]=t[i];
t[i]=tmpt;
strcpy(tmpxh,xh[i+1]);
strcpy(xh[i+1],xh[i]);
strcpy(xh[i],tmpxh);
}
}
}
for(tx=1;tx<373;tx++){
int s=0;
for(i=0;i<n;i++){
if (tx==t[i]){
s++;
strcpy(sc[s],xh[i]);
//printf("%d %d %s %s %d %d\n",i,s,xh[i],sc[s],y[i],r[i]);
}
else if(s>1){
printf("%d %d",y[i-1],r[i-1]);
for(h=1;h<=s;h++){
printf(" %s",sc[h]);
}
printf("\n");
s=0;
}
}
}
system("pause");
return 0;
}
题目 - 开关灯
来源
元培-From Whf
描述
假设有N盏灯(N为不大于5000的正整数),从1到N按顺序依次编号,有M个人(M为不大于N的正整数)也从1到M依次编号,第一个人(1号)将灯全部关闭,第二个人(2号)将编号为2的倍数的灯打开,第三个人(3号)将编号为3的倍数的灯做相反处理(即,将打开的灯关闭,将关闭的灯打开)。依照编号递增顺序,以后的人都和3号一样,将凡是自己编号倍数的灯做相反处理。请问:当第M个人操作之后,哪几盏灯是关闭的,按从小到大输出其编号,其间用逗号间隔。
关于输入
输入正整数N和M,以逗号间隔
关于输出
顺次输出关闭的灯的编号,其间用逗号间隔
例子输入
10,10
例子输出
1,4,9
#include <stdio.h>
int a[5001]={0};
int main()
{
int n,m,i,j;
scanf("%d,%d",&n,&m);
for(i=1;i<=m;i++){
for(j=1;j<=n;j++){
if(j%i==0)a[j]=1-a[j];
}
}
for(j=1;j<=n;j++){
if(a[j]==1)printf("%d,",j);
}
system("pause");
return 0;
}
题目 -出现次数超过一半的数
描述
给出一个含有n个整数的数组,请找出其中出现次数超过一半的数(n <= 1000)。
数组中的数大于-50且小于50。
关于输入
输入的第一行包含样例的组数m。
此后有m组样例,每组样例的第一行包含数组大小n,第二行上是这n个整数。
关于输出
如果存在这样的数,输出这个数;否则输出”no”。
例子输入
2
2
1 2
3
1 2 2
例子输出
no
2
#include <stdio.h>
#include <stdlib.h>
int main()
{
int m,n,i,j,k,sz[1001],js[100]={0},you=0;
scanf("%d",&m);
for(i=0;i<m;i++){
you=0;
scanf("%d",&n);
int half=n/2;
for(k=0;k<99;k++)
js[k] = 0;
for(j=0;j<n;j++){
scanf("%d",&sz[j]);
for(k=(-49);k<50;k++){
if(sz[j]==k)js[k+49]++;
}
}
for(k=0;k<99;k++){
if(js[k]>half)
{
printf("%d\n",k-49);
you=1;
}
}
if(you==0)printf("no\n");
}
system("pause");
return 0;
}
题目 - 谁考了第k名
来源
北大医学部07计算概论模拟考试1
描述
在一次考试中,每个学生的成绩都不相同,现知道了每个学生的学号和成绩,求考第k名学生的学号和成绩。
关于输入
第一行有两个整数,学生的人数n(1≤n≤100),和求第k名学生的k(1≤k≤n)。
其后有n行数据,每行包括一个学号(整数)和一个成绩(浮点数),中间用一个空格分隔。
关于输出
输出第k名学生的学号和成绩,中间用空格分隔。(注:请用%g输出成绩)
例子输入
5 3
90788001 67.8
90788002 90.3
90788003 61
90788004 68.4
90788005 73.9
例子输出
90788004 68.4
#include<stdio.h>
#define M 105
int main(){
int hao[M],i,j;
double fen[M];
int n,k;
scanf("%d %d",&n,&k);
for(i=0;i<n;i++){
scanf("%d %lf",&hao[i],&fen[i]);
}
for(i=1;i<=n;i++){
for(j=0;j<n-i;j++){
double tmp;
int num;
if(fen[j]>fen[j+1])
{tmp=fen[j+1];
fen[j+1]=fen[j];
fen[j]=tmp;
num=hao[i+1];
hao[i+1]=hao[i];
hao[i]=num;}
}
}
printf("%d %g",hao[n-k],fen[n-k]);
return 0;
}
题目 - 区间合并
描述
给定 n 个闭区间 [ai; bi],其中i=1,2,...,n。 这些区间可以用一组不间断的闭区间表示。我们的任务是找出这些区间是否可以用一个不间断的闭区间表示,如果可以的话将这个最小的闭区间输出,否则输出no。
关于输入
第一行为一个整数n,3 ≤ n ≤ 50000。表示输入区间的数量。在第i+1行上(1 ≤ i ≤ n),为两个整数 ai 和 bi ,整数之间用一个空格分隔,表示区间 [ai; bi](其中 1 ≤ ai ≤ bi ≤ 10000)。
关于输出
输出为一行,如果这些区间可以合并为一个闭区间,输出这个最小的闭区间,否则输出”no”
例子输入
5
5 6
1 5
10 10
6 9
8 10
例子输出
1 10
提示
用结构来存储区间信息并按照相应规则对区间排序
#include<stdio.h>
int main()
{
int n;
int a[50000];
int b[50000];
int k,i;
int temp,temp2;
int A=1;
int max=0;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d %d",&a[i],&b[i]);
}
for(k=1;k<n;k++)
{
for(i=0;i<n-k;i++)
{
if(a[i]>a[i+1])
{
temp=a[i];
a[i]=a[i+1];
a[i+1]=temp;
temp2=b[i];
b[i]=b[i+1];
b[i+1]=temp2;
}
}
}
for(i=0;i<n;i++)
{
if(b[i]<a[i+1])
{
A=0;
break;
}
else
{
if((b[i]>max))
{
max=b[i];
}
}
}
if(!A)
printf("no");
else
printf("%d %d",a[0],max);
system("pause");
return 0;
}
题目 - 距离排序
来源
POJ 3702
描述
给出三维空间中的n个点(不超过10个),求出n个点两两之间的距离,并按距离由大到小依次输出两个点的坐标及它们之间的距离。
关于输入
输入包括两行,第一行包含一个整数n表示点的个数,第二行包含每个点的坐标(坐标都是整数)。点的坐标的范围是0到100,输入数据中不存在坐标相同的点。
关于输出
对于大小为n的输入数据,输出n*(n-1)/2行格式如下的距离信息:
(x1,y1,z1)-(x2,y2,z2)=距离
其中距离保留到数点后面2位。
例子输入
4
0 0 0 1 0 0 1 1 0 1 1 1
例子输出
(0,0,0)-(1,1,1)=1.73
(0,0,0)-(1,1,0)=1.41
(1,0,0)-(1,1,1)=1.41
(0,0,0)-(1,0,0)=1.00
(1,0,0)-(1,1,0)=1.00
(1,1,0)-(1,1,1)=1.00
提示
注意:
冒泡排序满足下面的性质,选择排序和快速排序(qsort或sort)需要对下面的情况进行额外处理
使用冒泡排序时要注意边界情况的处理,保证比较的两个数都在数组范围内
1. 对于一行输出中的两个点(x1,y1,z1)和(x2,y2,z2),点(x1,y1,z1)在输入数据中应出现在点(x2,y2,z2)的前面。
比如输入:
2
0 0 0 1 1 1
输出是:
(0,0,0)-(1,1,1)=1.73
但是如果输入:
2
1 1 1 0 0 0
输出应该是:
(1,1,1)-(0,0,0)=1.73
2. 如果有两对点p1,p2和p3,p4的距离相同,则先输出在输入数据中靠前的点对。
比如输入:
3
0 0 0 0 0 1 0 0 2
输出是:
(0,0,0)-(0,0,2)=2.00
(0,0,0)-(0,0,1)=1.00
(0,0,1)-(0,0,2)=1.00
如果输入变成:
3
0 0 2 0 0 1 0 0 0
则输出应该是:
(0,0,2)-(0,0,0)=2.00
(0,0,2)-(0,0,1)=1.00
(0,0,1)-(0,0,0)=1.00
#include<stdio.h>
#include<math.h>
int main(){
int n,i,j;
scanf("%d",&n);
struct point{
int x;
int y;
int z;
}site[10];
for(i=0;i<n;i++)
scanf("%d%d%d",&site[i].x,&site[i].y,&site[i].z);
struct {
struct point A;
struct point B;
double d;
}pair[45],temp;
int N=0;
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++){
pair[N].A=site[i];
pair[N].B=site[j];
pair[N].d=sqrt(pow(site[i].x-site[j].x,2.0)+pow(site[i].y-site[j].y,2.0)+pow(site[i].z-site[j].z,2.0));
N++;
}
for(i=1;i<N;i++)
for(j=N-1;j>=i;j--)
if(pair[j].d>pair[j-1].d){
temp=pair[j];
pair[j]=pair[j-1];
pair[j-1]=temp;
}
for(i=0;i<N;i++)
printf("(%d,%d,%d)-(%d,%d,%d)=%.2lf\n",pair[i].A.x,pair[i].A.y,pair[i].A.z,pair[i].B.x,pair[i].B.y,pair[i].B.z,pair[i].d);
return 0;
}
题目 - 吃糖果问题
描述
名名的妈妈从外地出差回来,带了一盒好吃又精美的巧克力给名名(盒内共有 N 块巧克力,20 > N >0)。妈妈告诉名名每天可以吃一块或者两块巧克力。假设名名每天都吃巧克力,问名名共有多少种不同的吃完巧克力的方案。例如:如果N=1,则名名第1天就吃掉它,共有1种方案;如果N=2,则名名可以第1天吃1块,第2天吃1块,也可以第1天吃2块,共有2种方案;如果N=3,则名名第1天可以吃 1块,剩2块,也可以第1天吃2块剩1块,所以名名共有2+1=3种方案;如果N=4,则名名可以第1天吃1块,剩3块,也可以第1天吃2块,剩2块,共有3+2=5种方案。现在给定N,请你写程序求出名名吃巧克力的方案数目。
关于输入
输入只有1行,即整数N。
关于输出
输出只有1行,即名名吃巧克力的方案数。
例子输入
4
例子输出
5
#include <stdio.h>
#include <stdlib.h>
int fun(int n)
{
if(n==1)return 1;
if(n==2)return 2;
else return fun(n-1)+fun(n-2);
}
int main()
{
int n;
scanf("%d",&n);
printf("%d\n",fun(n));
return 0;
}
题目- 采药
描述
辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说: “孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。” 如果你是辰辰,你能完成这个任务吗?
关于输入
输入第一行有两个整数T(1 ≤ T ≤ 1000)和M(1 ≤ M ≤ 100),用一个空格隔开,T代表总共能够用来采药的时间,M代表山洞里的草药的数目。接下来的M行每行包括两个在1到100之间(包括1和100)的整数,分别表示采摘某株草药的时间和这株草药的价值。
关于输出
输出包括一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。
例子输入
70 3
71 100
69 1
1 2
例子输出
3
#include <stdio.h>
int totalTime, medics;
int value[100];
int time[100];
int max[1001];
int main()
{
scanf("%d%d", &totalTime, &medics);
int i, t;
for (i=0; i<medics; i++)
{
scanf("%d%d", &time[i], &value[i]);
}
for (i=0; i<medics; i++)
{
for (t=totalTime; t>0; t--)
{
if (time[i] <= t)
{
if (value[i] + max[t-time[i]] > max[t])//第i个的价值+不选第i个且用时为t-time[i-1]时最大价值
{
max[t] = value[i] + max[t-time[i]];
}
}
}
}
printf("%d\n", max[totalTime]);
system("pause");
return 0;
}
题目- 辉辉的日程表
描述
自从辉辉同学的光荣事迹出现在 2012 年计算概论期末考试题中之后,辉辉就火了,报社、电视台纷纷请他接受采访,学弟学妹也都想找他交流学习经验。从那时起,辉辉的日程都会排得很满,因为他每天都会先后收到多份预约请求。于是,他希望借助日程表的帮助,来确定可以接受其中哪些预约。
已知辉辉每天愿意接受预约的时间为 9 点到 21 点。排日程表时遵循先到先得的原则,且只有预约时间段完全可用时才能接受预约,接受之后这些时间就不能再次被预约了。请你帮助辉辉设计一个日程表管理程序。
关于输入
第 1 行为 1 个整数 n,表示收到 n 份预约,n ≤ 10。
之后有 n 行预约请求,每行包含 2 个整数 t1 和 t2 ,分别表示每份预约的开始时刻和结束时刻(精确到小时,例如 10 表示 10 点),9 ≤ t1 < t2 ≤ 21。预约请求按收到的先后顺序排列。
关于输出
n行,每行为 Y 或 N ,表示每份预约请求是否接受。
例子输入
6
9 11
10 13
11 15
18 21
16 19
16 18
例子输出
Y
N
Y
Y
N
Y
#include <stdio.h>
#include <stdlib.h>
#define M 14
int main()
{
int n,sz[M][2],is[24]={0},i,j,k,flag;
scanf("%d",&n);
for(i=0;i<n;i++){
flag=0;
scanf("%d%d",&sz[i][0],&sz[i][1]);
for(j=sz[i][0];j<sz[i][1];j++){
if(is[j]!=0){
printf("N\n");
flag=1;
break;
}
if(flag==1)break;
}
if(flag==1){
continue;
}
printf("Y\n");
for(j=sz[i][0];j<sz[i][1];j++){
is[j]=1;
}
}
system("pause");
return 0;
}
题目- 二进制加法
描述
给定两个二进制数 a 和 b ,计算 a + b 之和,输出和的二进制表示。
关于输入
输入有 2n + 1 行,第一行是 n,其余2n行,每两行一组,第一行是二进制数 a,第二行是二进制数 b;a 和 b 都大于 0 且不含前导 0 ,a、b 的位数不超过 100 位。
关于输出
输出 n 行 a + b 的结果,用二进制表示。
例子输入
2
1110011
11111111000
1010101
101010
例子输出
100001101011
1111111
提示
对 n 的取值没有特别的限制,只需要保证 n 是自然数即可。
#include<stdio.h>
#include <string.h>
int main()
{
int n,i,j,k;
int a,b,c,len;
scanf("%d",&n);
for(i=0;i<n;i++){
char fi[3][101]={0};
scanf("%s%s",fi[0],fi[1]);
a=0;
b=0;
c=0;
for(j=0;fi[0][j]!='\0';j++){
a=a*2+(fi[0][j]-'0');
}
for(j=0;fi[1][j]!='\0';j++){
b=b*2+(fi[1][j]-'0');
}
c=a+b;
len=(c==0)?1:0;
while(c>0){
fi[2][len++]=c%2+'0';
c/=2;
}
for(k=len-1;k>=0;k--){
printf("%c",fi[2][k]);
}
}
system("pause");
return 0;
}
题目- 神奇的幻方
来源
医学部计算概论2011年期末考试(李龙)
描述
在数学上,有一种n*n的矩阵,名字叫做幻方。它的含义是,这个矩阵的所有的行的和、所有的列的和以及两条对角线上的和,都是同一个数字。而且在这个矩阵中,从1到n*n各出现了一次并且只出现了一次。比如,中国历史上《易经》所用的著名的“洛书”,其本质就是一个三阶幻方:
8 1 6
3 5 7
4 9 2
可以看出,4+9+2,3+5+7,8+1+6,4+3+8,9+5+1,2+7+6,4+5+6与2+5+8这几个和都是15。现在,我们可以通过如下的方法,来构造一个(2k+1)*(2k+1)的幻方。
(1)第一个数字填在第一行的中间
(2)在填完第i个数字之后,第i+1个数字填在第i个数字的右上方
(3)如果第i个数字位于第一行,那么第i+1个数字就填在最后一行,位于i的右边
(4)如果第i个数字位于最后一列,那么第i+1个数字就填在第一列,位于i的上方
(5)如果i位于矩阵的右上角,或者i的右上角已有数字,那么i+1便填在i的下方
关于输入
一个整数n,3<=n<=21,n是一个奇数
关于输出
依以上方法做出的n*n的幻方。
例子输入
5
例子输出
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
开始编程
#include <stdio.h>
int main()
{
int a[22][22]={0};
int k,i,j,n;
scanf("%d",&n);
i=0;
j=n/2;
for(k=1;k<=n*n;k++){
//printf("%d*%d x|",i,j);
if(k==1){
a[i][j]=1;
continue;
}
else if(i==0&&(j==(n-1))){
i=1;
j=n-1;
// printf("%d*%d 3|",i,j);
}
else if(i==0){
i=n-1;
j+=1;
// printf("%d*%d 1|",i,j);
}
else if(j==(n-1)){
j=0;
i=i-1;
// printf("%d*%d 2|",i,j);
}
else{
// printf("%d*%d a|",i,j);
i=i-1;
j=j+1;
// printf("%d*%d a|",i,j);
if(i>=n)i=i-n;
else if(j>=n)j=j-n;
else if(i<0)i+=n;
else if(j<0)j+=n;
// printf("%d*%d 4|",i,j);
}
while(a[i][j]!=0){
i=i+2;
if(i>=n)i=i-n;
j=j-1;
if(j<0)j=n+j;
// printf("%d*%d 5|",i,j);
}
//printf("%d*%d\n",i,j);
a[i][j]=k;
int i1,j1;
// for(i1=0;i1<n;i1++){
// for(j1=0;j1<n;j1++){
// printf("%d ",a[i1][j1]);
// }
// printf("\n");
//}
//printf("%d*%d y|\n\n",i,j);
}
//printf("\n");
for(i=0;i<n;i++){
for(j=0;j<n-1;j++){
printf("%d ",a[i][j]);
}
printf("%d\n"a[i][j]);
}
system("pause");
return 0;
}
题目 - 试剂稀释
描述
一种药剂可以被稀释成不同的浓度供病人使用,且只能稀释不能增加浓度;又已知医院规定同一瓶药剂只能给某个病人以及排在他后面的若干人使用。现为了能最大限度利用每一瓶药剂(不考虑每一瓶容量),在给出的一个病人用药浓度序列(病人的顺序不能改变)中找出能同时使用一瓶药剂的最多人数。
关于输入
有两行,第一行是一个整数n,为病人的人数,假设不超过100;第二行为一个浮点数(double)序列,为每个病人的用药浓度,浮点数之间用一个空格隔开。
关于输出
展开阅读全文