第一题
标题:分数
1/1 + 1/2 + 1/4 + 1/8 + 1/16 + …
每项是前一项的一半,如果一共有20项,
求这个和是多少,结果用分数表示出来。
类似:3/2
当然,这只是加了前2项而已。分子分母要求互质。
注意:
需要提交的是已经约分过的分数,中间任何位置不能含有空格。请不要填写任何多余的文字或符号。
解析:等比数列求和公式,手算。
s=a1(1-q^n)/1-q;
第2题
标题:星期一
整个20世纪(1901年1月1日至2000年12月31日之间),一共有多少个星期一?
(不要告诉我你不知道今天是星期几)
注意:需要提交的只是一个整数,不要填写任何多余的内容或说明文字。
解析:计算总共多少天。对7求商取余数。再根据最后一天是周几往前走余数天看能够走到题目要求的周一,如果能则结果为为商加一,不能结果为商。
#include"stdio.h"
int month[12]={31,28,31,30,31,30,31,31,30,31,30,31};
int is_runian(int year)
{
if((year%4==0&&year% 100!=0)||year%400==0)//400的倍数,4的倍数但不是100的倍数。
{
return 1;
}
else
return 0;
}
int main()
{
int day=0;
int i;
for (i=1901;i<=2000;i++)
{
if (is_runian(i))
{
day=day+366;
}
else
{
day=day+365;
}
}
int yushu=0;
yushu=day%7;
day=day/7;
printf("%d %d",day,yushu);
return 0;
}
//输出5127 6 余数6 2000年12月31日是星期天。周日往前数6个,不是周一,所以不加一。答案5127
第3题
标题:乘积尾零
如下的10行数据,每行有10个整数,请你求出它们的乘积的末尾有多少个零?
5650 4542 3554 473 946 4114 3871 9073 90 4329
2758 7949 6113 5659 5245 7432 3051 4434 6704 3594
9937 1173 6866 3397 4759 7557 3070 2287 1453 9899
1486 5722 3135 1170 4014 5510 5120 729 2880 9019
2049 698 4582 4346 4427 646 9742 7340 1230 7683
5693 7015 6887 7381 4172 4341 2909 2027 7355 5649
6701 6645 1671 5978 2704 9926 295 3125 3878 6785
2066 4247 4800 1578 6652 4616 1113 6205 3264 2915
3966 5291 2904 1285 2193 1428 2265 8730 9436 7074
689 5510 8243 6114 337 4096 8199 7313 3685 211
解析:
直接计算会爆掉。末尾有多少零,因为只有2和5相乘,才会出现0。所以只要统计数中2和5最小的那个总数。
#include"stdio.h"
int result_2=0;//记录因子2的个数
int result_5=0;//记录因子5的个数
/*
将value分解看有多少个2多少个5
*/
void fenjie(int value)
{
result_2=0;
result_5=0;
while(value % 2==0) //统计因子2的个数
{
result_2++;
value=value/2;//统计i因子后除去i因子
}
while(value % 5==0)//统计因子5的个数
{
result_5++;
value=value/5;//统计i因子后除去i因子
}
}
int main()
{
int a[]={5650 ,4542 ,3554 ,473, 946, 4114 ,3871, 9073, 90, 4329,
2758 ,7949, 6113, 5659, 5245, 7432, 3051, 4434, 6704, 3594,
9937 ,1173, 6866, 3397, 4759, 7557, 3070, 2287, 1453, 9899,
1486 ,5722, 3135, 1170, 4014, 5510, 5120, 729, 2880, 9019,
2049, 698, 4582, 4346, 4427, 646, 9742, 7340 ,1230 ,7683,
5693 ,7015, 6887, 7381, 4172, 4341 ,2909, 2027 ,7355, 5649,
6701 ,6645 ,1671 ,5978 ,2704 ,9926, 295 ,3125 ,3878 ,6785,
2066 ,4247, 4800 ,1578, 6652, 4616 ,1113, 6205, 3264, 2915,
3966, 5291 ,2904 ,1285, 2193 ,1428 ,2265, 8730 ,9436 ,7074,
689 ,5510, 8243, 6114 ,337, 4096, 8199, 7313, 3685, 211
};
int len;
len = sizeof(a)/sizeof(int);//数组长度
int total_result2=0,total_result5=0; //储存2和5的个数
int result=0;//保存结果
for (int i=0;i<len;i++)
{
fenjie(a[i]);
total_result2=total_result2+result_2;
total_result5=total_result5+result_5;
}
if(total_result2>total_result5)
{
result=total_result5;
}
else
{
result=total_result2;
}
printf("%d",result);
return 0;
}
第4题
标题:第几个幸运数
到x星球旅行的游客都被发给一个整数,作为游客编号。x星的国王有个怪癖,他只喜欢数字3,5和7。
国王规定,游客的编号如果只含有因子:3,5,7,就可以获得一份奖品。我们来看前10个幸运数字是:3 5 7 9 15 21 25 27 35 45 因而第11个幸运数字是:49 小明领到了一个幸运数字 59084709587505,他去领奖的时候,人家要求他准确地说出这是第几个幸运数字,否则领不到奖品。请你帮小明计算一下,59084709587505是第几个幸运数字。需要提交的是一个整数,请不要填写任何多余内容。
解:分析国王喜欢的数 =3^a
*5^b
*7^c(a,b,c不可同时为0);
利用广度优先搜索做,用一个队列装幸运数,从3,5,7出发,依次将队首乘3,5,7的结果加入队尾(注意判重),直到出现目标59084709587505.注意找到目标后,目标位置之前还有符合题意的,还需要一次广度优先搜索。
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
long long q[10000];
int mul[3]={3,5,7};
int main()
{
memset(q,sizeof(q),0);//清零队列q
q[0]=3;
q[1]=5;
q[2]=7;
int front=0;//头指针
int rear=3;//尾指针位置为最后一个元素位置加1
while(front<rear) //队列不空
{
for(int i=0;i<3;i++)
{
if(q[front]*mul[i]>59084709587505)//大于59084709587505的排在后面的不加入队列。
continue;
long long t=q[front]*mul[i];//产生一个新的数
bool exist=0;//去重标志,等于0,数没在队列中,可以将新数加入队列。等于1,数已经在队列中,不可再加入队列。
for(int j=rear-1;j>=0;j--)
{ if(q[j]==t)
{
exist=1;//t在队列中
break;
}
}
if(!exist) //
{
q[rear]=t;
rear++;//将t入队
if(t==59084709587505)//此时队尾元素已经是59084709587505,但还存在front到rear之间的元素和3,5,7相乘的结果小于59084709587505的可能
{
for(int k=front;k<rear-1;)//以上<59084709587505的可能情况,都应加入队列中
{
for(int i=0;i<3;i++)
{
long long t=q[k]*mul[i];
if(t<59084709587505)
{
bool exist=0;//去重标志,等于0,数没在队列中,可以将新数加入队列。等于1,数已经在队列中,不可再加入队列。
for(int j=rear-1;j>=0;j--)
{ if(q[j]==t)
{
exist=1;//t在队列中
break;
}
}
if(!exist) //不在队列中入队
{
q[rear]=t;
rear++;
}
}
}
k++;
}
sort(q,q+rear);//对3到59084709587505的幸运数进行排序
int pos=rear-1;
while(q[pos]!=59084709587505)
{ pos--;//查找排序后的59084709587505所在的下标序号
}
cout<<pos+1<<endl;//因为是从队列位置从0开始的所以要加一
return 0;
}
}
}
front++; //头指针下移一个位置
}
return 0;
}
第6题
标题:航班时间
【问题背景】
小h前往美国参加了蓝桥杯国际赛。小h的女朋友发现小h上午十点出发,上午十二点到达美国,于是感叹到“现在飞机飞得真快,两小时就能到美国了”。
小h对超音速飞行感到十分恐惧。仔细观察后发现飞机的起降时间都是当地时间。由于北京和美国东部有12小时时差,故飞机总共需要14小时的飞行时间。
不久后小h的女朋友去中东交换。小h并不知道中东与北京的时差。但是小h得到了女朋友来回航班的起降时间。小h想知道女朋友的航班飞行时间是多少。
【问题描述】
对于一个可能跨时区的航班,给定来回程的起降时间。假设飞机来回飞行时间相同,求飞机的飞行时间。
【输入格式】
从标准输入读入数据。
一个输入包含多组数据。
输入第一行为一个正整数T,表示输入数据组数。
每组数据包含两行,第一行为去程的 起降 时间,第二行为回程的 起降 时间。
起降时间的格式如下
h1:m1:s1 h2:m2:s2
或
h1:m1:s1 h3:m3:s3 (+1)
或
h1:m1:s1 h4:m4:s4 (+2)
表示该航班在当地时间h1时m1分s1秒起飞,
第一种格式表示在当地时间 当日 h2时m2分s2秒降落
第二种格式表示在当地时间 次日 h3时m3分s3秒降落。
第三种格式表示在当地时间 第三天 h4时m4分s4秒降落。
对于此题目中的所有以 hⓂ️s 形式给出的时间, 保证 ( 0<=h<=23, 0<=m,s<=59 ).
【输出格式】
输出到标准输出。
对于每一组数据输出一行一个时间hh:mm:ss,表示飞行时间为hh小时mm分ss秒。
注意,当时间为一位数时,要补齐前导零。如三小时四分五秒应写为03:04:05。
【样例输入】
3
17:48:19 21:57:24
11:05:18 15:14:23
17:21:07 00:31:46 (+1)
23:02:41 16:13:20 (+1)
10:19:19 20:41:24
22:19:04 16:41:09 (+1)
【样例输出】
04:09:05
12:10:39
14:22:05
【限制与约定】
保证输入时间合法,飞行时间不超过24小时。
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
注意:
main函数需要返回0;
只使用ANSI C/ANSI C++ 标准;
不要调用依赖于编译环境或操作系统的特殊函数。
所有依赖的函数必须明确地在源文件中 #include
不能通过工程设置而省略常用头文件。
提交程序时,注意选择所期望的语言类型和编译器类型。
解析;去程:起飞时间1+时差+飞行时间=到达目的地时间1
归程:起飞时间2-时差+飞行时间=到达目的地时间2。
所以 起飞时间1+起飞时间2+2*飞行时间=到达目的地时间1+到达目的地时间2
即:飞行时间=(到达目的地时间1+到达目的地时间2-起飞时间1-起飞时间2)/2;
//#include"stdio.h"
#include"cstdio"
#include"iostream"
#include"string"
using namespace std;
int input1()
{
int hour,min,sec,time;
scanf("%d:%d:%d",&hour,&min,&sec);//输入的时候用英文的:
//printf("%d:%d:%d\n",hour,min,sec);
time=hour*3600+min*60+sec;
return time;
}
int input2()
{
int hour,min,sec,time,day=0;
char ch;
scanf("%d:%d:%d",&hour,&min,&sec);
ch=getchar();
while(ch!='\n')
{
if(isdigit(ch))//ch='0'-'9'返回1,否则返回0
{
day=ch-'0';
}
ch=getchar();
}
time=day*24*60*60+hour*60*60+min*60+sec;//化成秒
return time;
}
void output(int flytime) //秒转化为小时,分钟,秒输出
{
int hour,min,sec;
hour=flytime/3600;
min=(flytime-hour*3600)/60;
sec=flytime-hour*3600-min*60;
printf("%02d:%02d:%02d\n",hour,min,sec);//区域宽度为2,不足为0. 大于两位则原样输出
}
int main()
{
int N;
int flyTime=0;
int startFly1,startFly2,arriveFly1,arriveFly2;\
scanf("%d",&N);
while(N--)
{
startFly1=input1();//起飞时间1
arriveFly1=input2();
startFly2=input1();//起飞时间1
arriveFly2=input2();
flyTime=(arriveFly1+arriveFly2-startFly1-startFly2)/2;
output(flyTime);
}
return 0;
第9题
标题:倍数问题
【题目描述】
众所周知,小葱同学擅长计算,尤其擅长计算一个数是否是另外一个数的倍数。
但小葱只擅长两个数的情况,当有很多个数之后就会比较苦恼。
现在小葱给了你 n 个数,希望你从这 n 个数中找到三个数,使得这三个数的和是 K 的倍数,且这个和最大。
数据保证一定有解。
【输入格式】
从标准输入读入数据。
第一行包括 2 个正整数 n, K。
第二行 n 个正整数,代表给定的 n 个数。
【输出格式】
输出到标准输出。
输出一行一个整数代表所求的和。
【样例入】
4 3
1 2 3 4
【样例输出】
9
【样例解释】
选择2、3、4。
/*用数组num[n]储存n个数,第一个数有num[0]到num[n-1]种可能,第二个数有除去第一个数的n-1种可能,
第三个数有出去第二个数的n-2种可能/*
第一个数对 num[0]到num[n-1]种可能尝试,for循环
第二个数 num[0]到num[n-1]-1种可能尝试,for循环
第三个数 num[0]到num[n-1]-2种可能尝试,for循环
求三个数的方法相同,递归。深度优先搜索用递归实现,分而治之的思想。 */
#include"stdio.h"
int a[1000]={0};
int result[3];
int flag[1000]={0};//flag[i],用来标记num[i]是否已被使用,=1被使用,=0没有被使用
int sum;
int n,k;
int ans;
int i;
void dfs(int s) //深度优先搜索
{
if(s==3)
{
sum=result[0]+result[1]+result[2];
if((sum%k==0)&&sum>ans)
{
ans=sum;//更新结果
}
return;//返回结果
}
int i;
for(i=0;i<n;i++) //每一个数都有num[0]到num[n]种可能
{
if(!flag[i]) //判断a[i]是否被使用
{
result[s]=a[i];//将数据a[i]纳入结果
flag[i]=1;//标记a[i]被使用
dfs(s+1);//查找下一个数
flag[i]=0;//取消标记a[i]被使用
}
}
}
int main()
{
scanf("%d %d",&n,&k);//
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
dfs(0);//深度优先搜索
printf("%d",ans);
}