蓝桥杯省赛赛前集训题共14题.docx
《蓝桥杯省赛赛前集训题共14题.docx》由会员分享,可在线阅读,更多相关《蓝桥杯省赛赛前集训题共14题.docx(37页珍藏版)》请在冰豆网上搜索。
蓝桥杯省赛赛前集训题共14题
第1题:
星系炸弹(2015年省赛C/C++B组第2题)
在X星系的广袤空间中漂浮着许多X星人造“炸弹”,用来作为宇宙中的路标。
每个炸弹都可以设定多少天之后爆炸。
比如:
阿尔法炸弹2015年1月1日放置,定时为15天,则它在2015年1月16日爆炸。
有一个贝塔炸弹,2014年11月9日放置,定时为1000天,请你计算它爆炸的准确日期。
请填写该日期,格式为yyyy-mm-dd即4位年份2位月份2位日期。
比如:
2015-02-19
请严格按照格式书写。
不能出现其它文字或符号。
•结果:
2017-08-05
•解决方法:
用Excel拖
这个题会了的同学们把上课讲过的,课件上的,其他几道Excel拖动题都做一遍。
第2题:
(2015年校选拔赛C/C++B组第3题)
如果x的x次幂结果为10(参见【图1.png】),你能计算出x的近似值吗?
显然,这个值是介于2和3之间的一个数字。
请把x的值计算到小数后6位(四舍五入),并填写这个小数值。
注意:
只填写一个小数,不要写任何多余的符号或说明。
#include
#include
#include
usingnamespacestd;
intmain()
{
doublex;
for(x=2;x<=3;x+=1e-7)
{
if(abs(pow(x,x)-10)<1e-6)
cout<}
return0;
}
答案:
2.506184
其他类似题:
ALGO-23一元三次方程求解
第3题(全排列)
注意:
全排列必考!
全排列必考!
全排列必考!
重要的事要说三遍!
白打酒(2014年省赛本科B组第3题)
话说大诗人白,一生好饮。
幸好他从不开车。
一天,他提着酒壶,从家里出来,酒壶中有酒2斗。
他边走边唱:
无事街上走,提壶去打酒。
逢店加一倍,遇花喝一斗。
这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。
请你计算白遇到店和花的次序,可以把遇店记为a,遇花记为b。
则:
babaabbabbabbbb就是合理的次序。
像这样的答案一共有多少呢?
请你计算出所有可能方案的个数(包含题目给出的)。
答案:
14
解法1:
next_permutation的解法
#include
#include
usingnamespacestd;
intmain()
{
intp[15]={1,1,1,1,1,2,2,2,2,2,2,2,2,2,2};//1是店,2是花
intsum,cnt=0;
do
{
sum=2;
for(inti=0;i<15;i++)
if(p[i]==1)
sum<<=1;
elseif(p[i]==2)
sum--;
if(sum==0)t++;
}
while(next_permutation(p,p+14));//因为最后一次遇到的肯定是花,所以只排前14个数,不排最后一个
cout<return0;
}
解法2:
交换大法解法
#include
usingnamespacestd;
#defineN14//因为最后一次肯定是花,所以只排14个数
intt;
boolok(intp[],intbegin,intend)
{
for(inti=begin;iif(p[i]==p[end])
returnfalse;
returntrue;
}
voidperms(intp[],intstart)
{
inti;
if(start==N-1)
{
intsum=2;
for(i=0;iif(p[i]==1)
sum<<=1;
elseif(p[i]==2)
sum--;
if(sum==1)t++;//倒数第2次,剩1斗酒
return;
}
for(i=start;i{
if(ok(p,start,i))
{
swap(p[start],p[i]);
perms(p,start+1);
swap(p[start],p[i]);
}
}
}
intmain()
{
intp[]={1,1,1,1,1,2,2,2,2,2,2,2,2,2};//1是店,2是花
perms(p,0);
cout<return0;
}
解法3:
字符串全排列的解法
#include
#include
usingnamespacestd;
intmain()
{
strings="aaaaabbbbbbbbb";//a是店,b是花
intsum,cnt=0;
do
{
sum=2;
for(inti=0;i<15;i++)
if(s[i]=='a')
sum<<=1;
elseif(s[i]=='b')
sum--;
if(sum==1)t++;
}
while(next_permutation(s.begin(),s.end()));
cout<return0;
}
解法4:
递归解法
#include
usingnamespacestd;
intt=0;
voidf(inta,intb,intc)//a个店,b朵花,c升酒
{
if(a>5||b>9)return;
f(a+1,b,c*2);
f(a,b+1,c-1);
if(a==5&&b==9&&c==1)
cnt++;
}
intmain()
{
f(0,0,2);
cout<}
第4题(逻辑推理题)
练习系统ADV-143扶老奶奶过街
•一共有5个红领巾,编号分别为A、B、C、D、E,老奶奶被他们其中一个扶过了马路。
五个红领巾各自说话:
A:
我和E都没有扶老奶奶
B:
老奶奶是被C和E其中一个扶过大街的
C:
老奶奶是被我和D其中一个扶过大街的
D:
B和C都没有扶老奶奶过街
E:
我没有扶老奶奶
已知五个红领巾中有且只有2个人说的是真话,请问是谁扶这老奶奶过了街?
若有多个答案,在一行中输出,编号之间用空格隔开
例如
ABCDE(这显然不是正确答案)
解法1--位运算
#include
usingnamespacestd;
#defineN5
intmain()
{
inti,j,t,a[N];
for(i=0x10;i>0;i>>=1)
{
t=i;
for(j=N-1;j>=0;j--)
{
a[j]=t&1;
t>>=1;
}
//ABCDE5个变量存5个人的真假话状态,1为真话,0为假话
intA=(a[0]+a[4]==0);//A:
我和E都没有扶老奶奶
intB=(a[2]+a[4]==1);//B:
老奶奶是被C和E其中一个扶过大街的
intC=(a[2]+a[3]==1);//C:
老奶奶是被我和D其中一个扶过大街的
intD=(a[1]+a[2]==0);//D:
B和C都没有扶老奶奶过街
intE=(a[4]==0);//E:
我没有扶老奶奶
if(A+B+C+D+E==2)//5个人有且只有2个人说的是真话
{
for(j=0;j{
if(a[j])cout<}
}
}
return0;
}
解法2-全排列
#include
#include
usingnamespacestd;
#defineN5
intmain()
{
inta[N]={1,0,0,0,0};//1扶了。
0没扶。
do
{
//ABCDE5个变量存5个人的真假话状态,1为真话,0为假话
intA=(a[0]+a[4]==0);//A:
我和E都没有扶老奶奶
intB=(a[2]+a[4]==1);//B:
老奶奶是被C和E其中一个扶过大街的
intC=(a[2]+a[3]==1);//C:
老奶奶是被我和D其中一个扶过大街的
intD=(a[1]+a[2]==0);//D:
B和C都没有扶老奶奶过街
intE=(a[4]==0);//E:
我没有扶老奶奶
if(A+B+C+D+E==2)//5个人有且只有2个人说的是真话
{
for(inti=0;i{
if(a[i])cout<}
}
}
while(prev_permutation(a,a+N));
return0;
}
解法3-递归(大材小用了)
#include
usingnamespacestd;
#defineN5
inta[N];//1扶了。
0没扶。
voidf(intk)
{
inti;
if(k==N)
{
intsum=0;
for(i=0;isum+=a[i];
if(sum==1)//只有一个人扶了
{
//ABCDE5个变量存5个人的真假话状态,1为真话,0为假话
intA=(a[0]+a[4]==0);//A:
我和E都没有扶老奶奶
intB=(a[2]+a[4]==1);//B:
老奶奶是被C和E其中一个扶过大街的
intC=(a[2]+a[3]==1);//C:
老奶奶是被我和D其中一个扶过大街的
intD=(a[1]+a[2]==0);//D:
B和C都没有扶老奶奶过街
intE=(a[4]==0);//E:
我没有扶老奶奶
if(A+B+C+D+E==2)//5个人有且只有2个人说的是真话
{
for(i=0;i{
if(a[i])cout<}
}
}
return;
}
for(i=1;i>=0;i--)
{
a[k]=i;
f(k+1);
}
}
intmain()
{
f(0);
return0;
}
第5题:
牌型种数(2015年省赛C/C++B组第7题)
•小明被劫持到X赌城,被迫与其他3人玩牌。
•一副扑克牌(去掉大小王牌,共52),均匀发给4个人,每个人13。
•这时,小明脑子里突然冒出一个问题:
•如果不考虑花色,只考虑点数,也不考虑自己得到的牌的先后顺序,自己手里能拿到的初始牌型组合一共有多少种呢?
答案:
3598180
•
解法1:
暴力法,比较慢,5秒左右出答案,但不容易出错
#include
usingnamespacestd;
intmain()
{
inta1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13;//13种点数
intt=0;
for(a1=0;a1<=4;a1++)
for(a2=0;a2<=4;a2++)
for(a3=0;a3<=4;a3++)
for(a4=0;a4<=4;a4++)
for(a5=0;a5<=4;a5++)
for(a6=0;a6<=4;a6++)
for(a7=0;a7<=4;a7++)
for(a8=0;a8<=4;a8++)
for(a9=0;a9<=4;a9++)
for(a10=0;a10<=4;a10++)
for(a11=0;a11<=4;a11++)
for(a12=0;a12<=4;a12++)
for(a13=0;a13<=4;a13++)
{
if(a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13==13)
cnt++;
}
cout<return0;
}
解法2:
DFS+剪枝,秒杀
#include
usingnamespacestd;
intt=0;
voidf(intsum,intn)
{
inti;
if(sum>13||(13-n)*4+sum<13||n>13)return;//剪枝
if(sum==13)
{
cnt++;
return;
}
for(i=0;i<=4;i++)
{
f(sum+i,n+1);
}
}
intmain()
{
f(0,0);
cout<return0;
}
第6题:
单位分数(组合问题)
(2015年校选拔赛C/C++B组第6题)
•形如:
1/a的分数称为单位分数。
•可以把1分解为若干个互不相同的单位分数之和。
•例如:
•1=1/2+1/3+1/9+1/18
•1=1/2+1/3+1/10+1/15
•1=1/3+1/5+1/7+1/9+1/11+1/15+1/35+1/45+1/231
•等等,类似这样的分解无穷无尽。
•我们增加一个约束条件:
最大的分母必须不超过30
•请你求出分解为n项时的所有不同分解法。
•数据格式要求:
•输入一个整数n,表示要分解为n项(n<12)
•输出分解后的单位分数项,中间用一个空格分开。
•每种分解法占用一行,行间的顺序按照分母从小到大排序。
•例如,
•输入:
•4
•程序应该输出:
•1/21/31/81/24
•1/21/31/91/18
•1/21/31/101/15
•1/21/41/51/20
•1/21/41/61/12
•再例如,
•输入:
•5
•程序应该输出:
•1/21/31/121/211/28
•1/21/41/61/211/28
•1/21/41/71/141/28
•1/21/41/81/121/24
•1/21/41/91/121/18
•1/21/41/101/121/15
•1/21/51/61/121/20
•1/31/41/51/61/20
•资源约定:
•峰值存消耗<256M
•CPU消耗<2000ms
题目分析:
题目有点坑。
题意说不超过30,那理应可以等于30的,但是当n=5时,1/21/31/121/201/30也应该是正确的。
可是…,题目给的答案却没有这个解,所以,不能等于30
注意一定要剪枝,不剪的话会超过2000ms,剪枝之后大约428ms
#include
#include
usingnamespacestd;
inta[11];//n<12
intn;
voidC(intbegin,intm,doublesum)//从begin开始,选n个数中的第m个,已选出的数的和是sum
{
inti;
if(m1)//剪枝,很重要,不剪的话会超过2000ms
{
return;
}
if(m==n)
{
if(abs(sum-1)<1e-9)
{
for(i=0;i{
cout<<"1/"<if(i!
=n-1)
{
cout<<'';
}
}
cout<}
return;
}
for(i=begin;i<30;i++)
{
a[m]=i;
C(i+1,m+1,sum+1.0/i);
}
}
intmain()
{
cin>>n;
C(2,0,0);//从2开始,选n个数中的第0个,已选出的数的和是0
return0;
}
第7题(背包问题)
练习系统ALGO-115算法训练和为T
#include
usingnamespacestd;
longlonga[100];
intflag[100];
longlongT;
intn;
intt;
boolok()
{
for(inti=0;i{
if(flag[i]==1)
returntrue;
}
returnfalse;
}
voidf(intk,longlongsum)
{
if(k==n)
{
if(ok()&&sum==T)
{
for(inti=n-1;i>=0;i--)
{
if(flag[i])
{
cout<}
}
cout<cnt++;
}
return;
}
flag[k]=0;
f(k+1,sum);
flag[k]=1;
f(k+1,sum+a[k]);
}
intmain()
{
inti;
cin>>n;
for(i=n-1;i>=0;i--)
{
cin>>a[i];
}
cin>>T;
f(0,0);
cout<return0;
}
第8题(高精度整数和浮点数)
两个题,分别用Java的BigInteger和BigDecimal来做。
因为只求最后结果,如果用C/C++很麻烦,而用JAVABigInteger和BigDecimal来做很简单,所以不论C/C++还是JAVA组,都要学会以下两道题的JAVA解法。
1.梅森素数(6分)2013预赛JavaA组第3题
如果一个数字的所有真因子之和等于自身,则称它为“完全数”或“完美数”
例如:
6=1+2+3
28=1+2+4+7+14
早在公元前300多年,欧几里得就给出了判定完全数的定理:
若2^n-1是素数,则2^(n-1)*(2^n-1)是完全数。
其中^表示“乘方”运算,乘方的优先级比四则运算高,例如:
2^3=8,2*2^3=16,2^3-1=7
但人们很快发现,当n很大时,判定一个大数是否为素数到今天也依然是个难题。
因为法国数学家梅森的猜想,我们习惯上把形如:
2^n-1的素数称为:
梅森素数。
截止2013年2月,一共只找到了48个梅森素数。
新近找到的梅森素数太大,以至于难于用一般的编程思路窥其全貌,所以我们把任务的难度降低一点:
1963年,美国伊利诺伊大学为了纪念他们找到的第23个梅森素数n=11213,在每个寄出的信封上都印上了“2^11213-1是素数”的字样。
2^11213-1这个数字已经很大(有3000多位),请你编程求出这个素数的十进制表示的最后100位。
答案:
2191
2.黄金连分数(2013省赛题)
importjava.math.BigDecimal;
publicclassMain
{
publicstaticvoidmain(String[]args)
{
BigDecimalb=BigDecimal.ONE;
for(inti=0;i<500;i++)
{
b=b.add(BigDecimal.ONE);
b=BigDecimal.ONE.divide(b,101,BigDecimal.ROUND_HALF_UP);
}
System.out.println(b.setScale(100,BigDecimal.ROUND_HALF_UP));
}
}
第9题(进制转换)
1.十进制转十六进制(递归),练习系统-基础练习-BASIC-10
问题描述
十六进制数是在程序设计时经常要使用到的一种整数的表示方式。
它有0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F共16个符号,分别表示十进制数的0至15。
十六进制的计数方法是满16进1,所以十进制数16在十六进制中是10,而十进制的17在十六进制中是11,以此类推,十进制的30在十六进制中是1E。
给出一个非负整数,将它表示成十六进制的形式。
输入格式
输入包含一个非负整数a,表示要转换的数。
0<=a<=2147483647
输出格式
输出这个整数的16进制表示
样例输入
30
样例输出
1E
#include
usingnamespacestd;
strings="0123456789ABCDEF";
voidf(intn)
{
if(n>=16)f(n>>4);
cout<
}
intmain()
{
intn;
cin>>n;
f(n);
return0;
}
2.//十六进制转十进制//练习系统-基础练习-BASIC-11
问题描述
从键盘输入一个不超过8位的正的十六进制数字符串,将它转换为正的十进制数后输出。
注:
十六进制数中的10~15分别用大写的英文字母A、B、C、D、E、F表示。
样例输入
FFFF
样例输出
65535
#include
usingnamespacestd;
intmain()
{
inti,t;
unsignedsum=0;
strings;
cin>>s;
for(i=0;s[i];i++)
{
t=s[i]<='9'?
s[i]-'