目录
2012第三题:比酒量
题目描述
有一群海盗(不多于20人),在船上比拼酒量。过程如下:打开一瓶酒,所有在场的人平分喝下,有几个人倒下了。再打开一瓶酒平分,又有倒下的,再次重复----直到开了第4瓶酒,坐着的已经所剩无几,海盗船长也在其中。当第4瓶酒平分喝下后,大家都倒下了。等船长醒来,发现海盗船搁浅了。他在航海日志中写到:“…昨天,我正好喝了一瓶…奉劝大家,开船不喝酒,喝酒别开船…”
请你根据这些信息,推断开始有多少人,每一轮喝下来还剩多少人。如果有多个可能的答案,请列出所有答案,每个答案占一行。格式是:人数,人数,…
例如,有一种可能是:20,5,4,2,0
题目分析
设开始有x人,第一轮喝醉a人,第二轮喝醉b人,第三轮喝醉c人。
顺便提一下,要注意一下数据类型,1.0/2 和 1/2 是不一样的。
题目代码
#include <iostream>
using namespace std;
int main()
{
for(int x=20; x>0; x--)
{
for(int a=1; a<20; a++)
{
for(int b=1; b<20-a; b++)
{
for(int c=1; c<20-a-b; c++)
{
if((1.0/x+1.0/(x-a)+1.0/(x-a-b)+1.0/(x-a-b-c))==1)
{
cout<<x<<" "<<x-a<<" "<<x-a-b<<" "<<x-a-b-c<<endl;
}
}
}
}
}
return 0;
}
题目答案
20 5 4 2
18 9 3 2
15 10 3 2
12 6 4 2
2013第三题:第39级台阶
题目描述
小明刚刚看完电影《第39级台阶》,离开电影院的时候,他数了数礼堂前的台阶数,恰好是39级!站在台阶前,他突然又想着一个问题:
如果我每一步只能迈上1个或2个台阶,先迈左脚,然后左右交替,最后一步是迈右脚,也就是说一共要走偶数步。那么,上完39级台阶,有多少种不同的上法呢?
请你利用计算机的优势,帮助小明寻找答案。要求提交的是一个整数。
题目分析
这题使用递归算法
递归的终止条件:当步数达到39时候,终止递归
递归的两个入口:单步上台阶,和两步上台阶
题目代码
#include<iostream>
using namespace std;
//num表示一共的台阶数
//time表示走了多少次
int DFS(int num,int time)
{
if(num>39)
{
return 0;
}
if(num==39)
{
if(time%2==0)
{
return 1;
}
return 0;
}
// 单步跨 两步跨
return DFS(num+1,time+1)+DFS(num+2,time+1);
}
int main()
{
int ans = DFS(1,1)+DFS(2,1);
cout << ans;
return 0;
}
#include <iostream>
using namespace std;
int sum=0;
//(台阶,步数)
void dfs(int tj,int num){
if(tj>39)return;
if(tj==39){
if(num%2==0){
sum++;
}
return;
}
dfs(tj+1,num+1);
dfs(tj+2,num+1);
}
int main()
{
dfs(0,0);
cout <<sum<< endl;
return 0;
}
题目答案
51167078
2014第三题:李白打酒
题目描述
话说大诗人李白,一生好饮。幸好他从不开车。
一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:
无事街上走,提壶去打酒。
逢店加一倍,遇花喝一斗。
这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。
请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。像这样的答案一共有多少呢?请你计算出所有可能方案的个数(包含题目给出的)。
题目分析
递归主要找出 临界值
进入下一步的每个变量的变化
题目代码
#include<iostream>
using namespace std;
int sum=0;
//x表示还有几次遇到店的机会
//y表示还有几次遇到花的机会
//c表示当前酒的斗数
int f(int x,int y,int c)
{
if(x<0||y<0)//终止条件
return 0;
if(x==0&&y==1&&c==1)//临界条件
sum=sum+1;
//如果遇到酒店
if(x>0)
f(x-1,y,c*2);
//如果遇到花
if(y>0)
f(x,y-1,c-1);
return 0;
}
int main()
{
f(5,10,2);
cout<<sum<<endl;
return 0;
}
法二:
#include <iostream>
using namespace std;
int sum=0;
//(dian,hua,jiu)
void dfs(int d,int h,int j){
if(d>5||h>9){
return;
}
if(d==5&&h==9){
if(j==1){
sum ++;
}
return;
}
//遇到花
dfs(d,h+1,j-1);
//遇到店
dfs(d+1,h,j*2);
}
int main()
{
dfs(0,0,2);
cout <<sum<< endl;
return 0;
}
题目答案:
14
2015第三题:三羊献瑞
题目描述
观察下面的加法算式:
祥 瑞 生 辉
+ 三 羊 献 瑞
-------------------
三 羊 生 瑞 气
(如果有对齐问题,可以参看【图1.jpg】)其中,相同的汉字代表相同的数字,不同的汉字代表不同的数字。请你填写“三羊献瑞”所代表的4位数字(答案唯一),不要填写任何多余内容。
题目分析
从文字中可以得出 祥 三 为非零的数,且 三 为1
这里可以用暴力,7层循环
a 祥,b 瑞,c 生,d 辉,e 羊,f 献,g 气;
题目代码
#include <iostream>
using namespace std;
int main()
{
//a 祥,b 瑞,c 生,d 辉,e 羊,f 献,g 气;
int a,b,c,d,e,f,g;
for(int a=2; a<=9; a++)
{
for(int b=0; b<=9; b++)
{
if(b==1)
continue;
for(int c=0; c<=9; c++)
{
if(c==1)
continue;
for(int d=0; d<=9; d++)
{
if(d==1)
continue;
for(int e=0; e<=9; e++)
{
if(e==1)
continue;
for(int f=0; f<=9; f++)
{
if(f==1)
continue;
for(int g=0; g<=9; g++)
{
if(g==1)
continue;
if((a!=b)&&(a!=c)&&(a!=d)&&(a!=e)&&(a!=f)&&(a!=g)&&(b!=c)&&(b!=d)&&(b!=e)&&(b!=f)&&(b!=g)&&(c!=d)&&(c!=e)&&(c!=f)&&(c!=g)&&(d!=e)&&(d!=f)&&(d!=g)&&(e!=f)&&(e!=g)&&(f!=g))
{
if((a*1000+b*100+c*10+d)+(1000+e*100+f*10+b)==(10000+e*1000+c*100+b*10+g))
{
cout<<"1"<<e<<f<<b<<endl;
}
}
}
}
}
}
}
}
}
return 0;
}
题目答案
1085
2016第三题:凑算式
题目描述
B DEF
A + — + ——— = 10
C GHI
这个算式中AI代表19的数字,不同的字母代表不同的数字。
比如:
6+8/3+952/714 就是一种解法,
5+3/1+972/486 是另一种解法。
这个算式一共有多少种解法?
注意:你提交应该是个整数,不要填写任何多余的内容或说明性文字。
题目分析
暴力循环
题目代码
#include <iostream>
using namespace std;
int main()
{
int a,b,c,d,e,f,g,h,i,num=0;
for(int a=1;a<=9;a++){
for(int b=1;b<=9;b++){
for(int c=1;c<=9;c++){
for(int d=1;d<=9;d++){
for(int e=1;e<=9;e++){
for(int f=1;f<=9;f++){
for(int g=1;g<=9;g++){
for(int h=1;h<=9;h++){
for(int i=1;i<=9;i++){
if(a!=b&&a!=c&&a!=d&&a!=e&&a!=f&&a!=g&&a!=h&&a!=i&&b!=c&&b!=d&&b!=e&&b!=f&&b!=g&&b!=h&&b!=i&&c!=d&&c!=e&&c!=f&&c!=g&&c!=h&&c!=i&&d!=e&&d!=f&&d!=g&&d!=h&&d!=i&&e!=f&&e!=g&&e!=h&&e!=i&&f!=g&&f!=h&&f!=i&&g!=h&&g!=i&&h!=i)
if((double)a+(double)b/(double)c+(double)(d*100+e*10+f)/(double)(g*100+h*10+i)==10){
num++;
}
}
}
}
}
}
}
}
}
}
cout <<num<< endl;
return 0;
}
题目答案
29
2017第三题:承压计算
题目描述
X星球的高科技实验室中整齐地堆放着某批珍贵金属原料。
每块金属原料的外形、尺寸完全一致,但重量不同。
金属材料被严格地堆放成金字塔形。
7
5 8
7 8 8
9 2 7 2
8 1 4 9 1
8 1 8 8 4 1
7 9 6 1 4 5 4
5 6 5 5 6 9 5 6
5 5 4 7 9 3 5 5 1
7 5 7 9 7 4 7 3 3 1
4 6 4 5 5 8 8 3 2 4 3
1 1 3 3 1 6 6 5 5 4 4 2
9 9 9 2 1 9 1 9 2 9 5 7 9
4 3 3 7 7 9 3 6 1 3 8 8 3 7
3 6 8 1 5 3 9 5 8 3 8 1 8 3 3
8 3 2 3 3 5 5 8 5 4 2 8 6 7 6 9
8 1 8 1 8 4 6 2 2 1 7 9 4 2 3 3 4
2 8 4 2 2 9 9 2 8 3 4 9 6 3 9 4 6 9
7 9 7 4 9 7 6 6 2 8 9 4 1 8 1 7 2 1 6
9 2 8 6 4 2 7 9 5 4 1 2 5 1 7 3 9 8 3 3
5 2 1 6 7 9 3 2 8 9 5 5 6 6 6 2 1 8 7 9 9
6 7 1 8 8 7 5 3 6 5 4 7 3 4 6 7 8 1 3 2 7 4
2 2 6 3 5 3 4 9 2 4 5 7 6 6 3 2 7 2 4 8 5 5 4
7 4 4 5 8 3 3 8 1 8 6 3 2 1 6 2 6 4 6 3 8 2 9 6
1 2 4 1 3 3 5 3 4 9 6 3 8 6 5 9 1 5 3 2 6 8 8 5 3
2 2 7 9 3 3 2 8 6 9 8 4 4 9 5 8 2 6 3 4 8 4 9 3 8 8
7 7 7 9 7 5 2 7 9 2 5 1 9 2 6 5 3 9 3 5 7 3 5 4 2 8 9
7 7 6 6 8 7 5 5 8 2 4 7 7 4 7 2 6 9 2 1 8 2 9 8 5 7 3 6
5 9 4 5 5 7 5 5 6 3 5 3 9 5 8 9 5 4 1 2 6 1 4 3 5 3 2 4 1
X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X
其中的数字代表金属块的重量(计量单位较大)。
最下一层的X代表30台极高精度的电子秤。假设每块原料的重量都十分精确地平均落在下方的两个金属块上,最后,所有的金属块的重量都严格精确地平分落在最底层的电子秤上。电子秤的计量单位很小,所以显示的数字很大。
工作人员发现,其中读数最小的电子秤的示数为:2086458231
请你推算出:读数最大的电子秤的示数为多少?
注意:需要提交的是一个整数,不要填写任何多余的内容。
题目分析
该题目就是一个模拟题,就是数据量偏大,使用 long long int类型来计算就可。提供官方代码
题目代码
#include <iostream>
#include <algorithm>
#include <stdio.h>
using namespace std;
#include<cmath>
typedef long long LL;
LL arr[30][30];
int main(int argc, const char * argv[]) {
LL factor=1;
for (int i = 0; i < 30; ++i) {
factor<<=1;
}
// 输入
for (int i = 0; i < 29; ++i) {
for (int j = 0; j <= i; ++j) {
LL a=0;
scanf("%lld",&a);
arr[i][j]=a*factor;
}
}
//平分数据
for (int i = 0; i < 29; ++i) {
for (int j = 0; j <=i ; ++j) {
LL ha =arr[i][j]/2;
arr[i+1][j]+=ha;
arr[i+1][j+1]+=ha;
}
}
//排序
sort(arr[29],arr[29]+30);
cout<<arr[29][0]/2<<","<<arr[29][29]/2<<endl;
return 0;
}
题目答案
2086458231,72665192664
2018第三题:乘积尾零
题目描述
如下的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
注意:需要提交的是一个整数,表示末尾零的个数。不要填写任何多余内容。
题目分析
这里10由可以由 2 和 5相乘得到,所以只要计算每个数中2和5的个数就行,最后最小个数的构成零的个数,例如150=3*5*5*2,有两个5,一个2,即150的末尾有一个零。
题目代码
#include <iostream>
using namespace std;
int main()
{
int num_5=0,num_2=0;
int data[100]= {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
};
for(int i=0; i<100; i++)
{
while(1)
{
if(data[i]%5==0)
{
num_5++;
data[i]=data[i]/5;
}
else if(data[i]%2==0)
{
num_2++;
data[i]=data[i]/2;
}
else
{
break;
}
}
}
cout <<min(num_2,num_5)<<endl;
return 0;
}
题目答案
31
2019第三题:数列求值
题目描述
给定数列1,1,1,3,5,9,17,…,从第4项开始,每项都是前3项的和。求第20190324项的最后4位数字。
题目分析
用数组保存三项值,通过对3取余依次将数字加上去。应为保留最后四位数字,所以每次计算过后需要用10000取余,不然会溢出.
题目代码
#include <iostream>
using namespace std;
int main()
{
//给定数列1,1,1,3,5,9,17,…,从第4项开始,每项都是前3项的和。求第20190324项的最后4位数字。
int num[3]={1,1,1};
int index=4;
while(index<=20190324){
num[index%3]=num[1]+num[2]+num[0];
num[index%3]=num[index%3]%10000;
index++;
}
cout<<num[(index-1)%3];
return 0;
}
2020第一场 第三题:合并检测
题目描述
新冠疫情由新冠病毒引起,最近在 A 国蔓延,为了尽快控制疫情, A 国准备给大量民众进病毒核酸检测。
然而,用于检测的试剂盒紧缺。
为了解决这一困难,科学家想了一个办法:合并检测。即将从多个人( k 个)采集的标本放到同一个试剂盒中进行检测。如果结果为阴性,则说明这 k 个人都是阴性,用一个试剂盒完成了 k 个人的检测。如果结果为阳性,则说明至少有一个人为阳性,需要将这 k 个人的样本全部重新独立检测(从理论上看,如果检测前 k−1 个人都是阴性可以推断出第 k 个人是阳性,但是在实际操作中不会利用此推断,而是将 k 个人独立检测),加上最开始的合并检测,一共使用了 k+1 个试剂盒完成了 k 个人的检测。
A 国估计被测的民众的感染率大概是 1%,呈均匀分布。请问 k 取多少能最节省试剂盒?
题目分析
这里概率为1%,我们不妨设置测试人员为100,其中有1个感染者,然后就是分类讨论每组人数k可以被100整除和不可以被整除的情况
可以被100整除 100/k+k
不可以被100整除 100/k+k+1,
题目代码
#include<iostream>
using namespace std;
int main()
{
int ans = 0;
int sum = 1000;//设需要的试剂盒,就是求sum最小值
for(int i = 1; i <= 100; i++){
if(100%i==0)
{
if(100/i+i<sum){
sum=100/i+i;
ans = i;
}
}
else
{
if(100/i+1+i<sum)
{
sum=100/i+1+i;
ans=i;
}
}
}
cout << ans <<endl;
}
题目答案
10
2020第二场 第三题:蛇形填数
题目描述
如下图所示,小明用从1开始的正整数“蛇形”填充无限大的矩阵。容易看出矩阵第二行第二列中的数是5。请你计算矩阵中第20行第20列的数是多少?
1 2 6 7 15 …
3 5 8 14 …
4 9 13 …
10 12 …
11 …
题目分析
可以将图形顺时针旋转45度,我们可以发现20行20列应该位于第49层的中间一个,然后模拟就可以算出来了
1行1列 1
3 2
2行2列 4 5 6
10 9 8 7
3行3列 11 12 13 14 15
.................
规律:蛇形矩阵的1行1列为自然数的第1个奇数,蛇形矩阵的2行2列为自然数的第2个奇数和它前面所有数的和减去(2-1),蛇形矩阵的3行3列为自然数的第3个奇数和它前面所有数的和减去(3-1)~
例如第1行1列是1,
第2行2列是5,1+2+3=6, 6 -(2-1)=5
第3行3列是13,1+2+3+4+5=15,15-(3-1)=13
~ ~ ~
题目代码
#include <iostream>
using namespace std;
int main()
{
int num=0,sum=0;
for(int i=1;i<100;i++){
sum=sum+i;
if(i%2==1){
num++;
}
if(num==20){
int a=num-1;
sum=sum-a;
break;
}
}
cout <<sum<< endl;
//法二
//从一开始的第20个奇数temp,其实就是2*20-1=39
int temp =1,sum=0;
for(int i=1; i<20; i++)
{
temp =temp+2;
}
for(int j=1; j<=temp; j++)
{
sum =sum+j;
}
cout<<sum-19;
return 0;
}
题目答案
761