2014 第六届蓝桥杯校内赛解题报告 答案

仅仅留做以后回过头来勉励自己,转载请注明出处。

1.

输入一个字符串,求它包含多少个单词。单词间以一个或者多个空格分开。
第一个单词前,最后一个单词后也可能有0到多个空格。
比如:" abc    xyz" 包含两个单词,"ab   c   xyz    "  包含3个单词。

如下的程序解决了这个问题,请填写划线部分缺失的代码。

注意:只填写划线部分的代码,不要填写任何多余的内容。比如已经存在的小括号,注释或说明文字等。


int get_word_num(char* buf)
{
int n = 0;   
int tag = 1; 
char* p = buf;
for(;*p!=0 && *p!=13 && *p!=10;p++){
if(*p==' ' && tag==0) tag=1;
if(________________ ) { n++; tag=0; }   //填空
}
return n;
}

int main()
{
char buf[1000];
fgets(buf,1000,stdin);
printf("%d\n", get_word_num(buf));
return 0;
}


答案:tag==1&&*p!=' ' 

这题很水,我就不说什么了。
2.
1/1 + 1/2 + 1/3 + 1/4 + ... 在数学上称为调和级数。

它是发散的,也就是说,只要加上足够多的项,就可以得到任意大的数字。

但是,它发散的很慢:

前1项和达到 1.0
前4项和才超过 2.0
前83项的和才超过 5.0

那么,请你计算一下,要加多少项,才能使得和达到或超过 15.0 呢?

请填写这个整数。

注意:只需要填写一个整数,不要填写任何多余的内容。比如说明文字。

答案:1835421  
代码: 
 
#include <cstdio>
int main() {
double s=0.0;
int i;
for(i=1;s<=15.0;i++){
s+=1.0/i;
}
printf("%d",i-1);
return 0;
}
这题有个坑点,考试的时候被坑,当时考试的时候忘了初始化s变量,结果跑了10分钟没结果,然后拉excel表拉了半小时T_T我也是醉了,最后回头发现忘了初始化变量,,我的时间啊T_T,最后最后,尼玛坑爹的是忘了i要减一输出!!!!就把1835422提交了T_T,,答案在上头。。。。赶紧码字滚下去,不想看见悲伤的结果T_T。
3. 

如果x的x次幂结果为10(图就不传了把,,前边的描述已经够了),你能计算出x的近似值吗?

显然,这个值是介于2和3之间的一个数字。

请把x的值计算到小数后6位(四舍五入),并填写这个小数值。

注意:只填写一个小数,不要写任何多余的符号或说明。

答案:  2.506184
代码:
#include <cstdio>
#include <cmath>
int main() {
double x=2.4;
for(;x<3;x+=0.00000001){
if(fabs(pow(x,x)-10.0)<0.000001){
printf("%.8lf\n",x);
}
}
return 0;
}
这题考的就是精度的控制,需要注意的是小数点最后几位别弄错了  ,多输出几位小数看看,至于方法,我这里用的是暴力穷举了,有更好的方法是咱高数大神想出来的,穷举确实慢,但这也是足够出答案了,反正这题是结果填空,至于好的方法,我提个名字,牛顿迭代法,还有更高级的牛顿下山法,想要代码的去找大神吧o(≧v≦)o~~,代码也不长,只需30次以内的运算就能出结果,赞呐~~~~
4. 

今有7对数字:两个1,两个2,两个3,...两个7,把它们排成一行。
要求,两个1间有1个其它数字,两个2间有2个其它数字,以此类推,两个7之间有7个其它数字。如下就是一个符合要求的排列:

17126425374635

当然,如果把它倒过来,也是符合要求的。

请你找出另一种符合要求的排列法,并且这个排列法是以74开头的。

注意:只填写这个14位的整数,不能填写任何多余的内容,比如说明注释等。


答案: 74151643752362
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
char per[15]="74112243735566";
bool p[14];
int main()
{
int i;
do
{
if(per[1]!='4') break;
memset(p,0,sizeof(p));
for(i=0;i<14;i++)
{
if(!p[i])
{
if(per[i]==per[i+per[i]-47])
p[i]=p[i+per[i]-47]=1;
else break;
}
}
if(i==14) puts(per);
}while(next_permutation(per+2,per+14));
}
 这题又是一大悲剧,考试的时候忘了全排列函数,忘了算法头文件,通过目录搜索也是醉了,最后感觉没时间就先放放,没想到回过头来真没时间做这题了T_T,好多大神直接手算就解决出来了,不过代码也很快很短,特别是用上stl的全排列一下就出来了。悲剧!!
5. 

  勾股定理,西方称为毕达哥拉斯定理,它所对应的三角形现在称为:直角三角形。

  已知直角三角形的斜边是某个整数,并且要求另外两条边也必须是整数。

  求满足这个条件的不同直角三角形的个数。

【数据格式】
输入一个整数 n (0<n<10000000) 表示直角三角形斜边的长度。
要求输出一个整数,表示满足条件的直角三角形个数。

例如,输入:
5
程序应该输出:
1

再例如,输入:
100
程序应该输出:
2

再例如,输入:
3
程序应该输出:
0


资源约定:
峰值内存消耗 < 256M
CPU消耗  < 1000ms


请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。

提交时,注意选择所期望的编译器类型。


代码:
#include <cstdio>
#include <cmath>
int main() {
long long aa,bb,cc;
int a,b,c,ans=0;
scanf("%d",&c);
cc=c*c;
for(a=1;a<c/sqrt(2);a++){
aa=a*a;
b=sqrt(cc-aa);
if(b*b+aa==cc)ans++;
}
printf("%d",ans);
return 0;
}
也是很简单的水题,不过要注意的是平方之后容易超出int的范围,用上longlong,最好不要用double,double在判等的时候精度问题容易错。暴力的时候穷举到 c/ sqrt(2)就行了,也是一个优化点。

6. 

你一定听说过“数独”游戏。
如【图1.png】,玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个同色九宫内的数字均含1-9,不重复。

数独的答案都是唯一的,所以,多个解也称为无解。

本图的数字据说是芬兰数学家花了3个月的时间设计出来的较难的题目。但对会使用计算机编程的你来说,恐怕易如反掌了。

本题的要求就是输入数独题目,程序输出数独的唯一解。我们保证所有已知数据的格式都是合法的,并且题目有唯一的解。

格式要求,输入9行,每行9个数字,0代表未知,其它数字为已知。
输出9行,每行9个数字表示数独的解。

例如:
输入(即图中题目):
005300000
800000020
070010500
400005300
010070006
003200080
060500009
004000030
000009700

程序应该输出:
145327698
839654127
672918543
496185372
218473956
753296481
367542819
984761235
521839764

再例如,输入:
800000000
003600000
070090200
050007000
000045700
000100030
001000068
008500010
090000400

程序应该输出:
812753649
943682175
675491283
154237896
369845721
287169534
521974368
438526917
796318452

资源约定:
峰值内存消耗 < 256M
CPU消耗  < 2000ms


请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。

提交时,注意选择所期望的编译器类型。

代码:
#include <cstdio>
#include <string.h>
int a[9][9],row[9][10],col[9][10],g[10][10];
void fun(int x,int y){
if(x==9&&y==0){
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
printf("%d ",a[i][j]);
}
puts("");
}
}
if(a[x][y]!=0){
if(y==8){
fun(x+1,0);
}
else
fun(x,y+1);
}else
for(int i=1;i<=9;i++){
if(row[x][i]==1||col[y][i]==1||g[(x)/3*3+(y)/3][i]==1)
continue;
a[x][y]=i;
row[x][i]=1;
col[y][i]=1;
g[(x)/3*3+(y)/3][i]=1;
if(y==8)
fun(x+1,0);
else
fun(x,y+1);
row[x][i]=0;
col[y][i]=0;
g[(x)/3*3+(y)/3][i]=0;
a[x][y]=0;
}
int main() {
int n;
scanf("%d",&n);
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
scanf("%1d",&a[i][j]);
if(a[i][j]!=0){
row[i][a[i][j]]=1;
col[j][a[i][j]]=1;
g[(i)/3*3+(j)/3][a[i][j]]=1;
}
}
}
fun(0,0);
return 0;
}
 这题才算的上有点难度了,这是oj上原题的一个题,思路就是穷举搜索,连剪枝都不需要,优化方案就在于搜到结果后的退出(不优化时间也挺快),还有个难度就是这题判断的时候有个小九方格的映射,另这题可以拉成一维的写,我这个代码不是最好的,有点长,我也懒的改了,了解一下思路就行。
7. 

G将军有一支训练有素的军队,这个军队除开G将军外,每名士兵都有一个直接上级(可能是其他士兵,也可能是G将军)。现在G将军将接受一个特别的任务,需要派遣一部分士兵(至少一个)组成一个敢死队,为了增加敢死队队员的独立性,要求如果一名士兵在敢死队中,他的直接上级不能在敢死队中。
请问,G将军有多少种派出敢死队的方法。注意,G将军也可以作为一个士兵进入敢死队。
输入格式
输入的第一行包含一个整数n,表示包括G将军在内的军队的人数。军队的士兵从1至n编号,G将军编号为1。
接下来n-1个数,分别表示编号为2, 3, ..., n的士兵的直接上级编号,编号i的士兵的直接上级的编号小于i。
输出格式
输出一个整数,表示派出敢死队的方案数。由于数目可能很大,你只需要输出这个数除10007的余数即可。
样例输入1
3
1 1
样例输出1
4
样例说明
这四种方式分别是:
1. 选1;
2. 选2;
3. 选3;
4. 选2, 3。
样例输入2
7
1 1 2 2 3 3
样例输出2
40

数据规模与约定
对于20%的数据,n ≤ 20;
对于40%的数据,n ≤ 100;
对于100%的数据,1 ≤ n ≤ 100000。
资源约定:
峰值内存消耗 < 256M
CPU消耗  < 2000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。

提交时,注意选择所期望的编译器类型。


代码:
#include <cstdio>
#include <vector>
using namespace std;
int dp[100001][2],a[100001];
vector<int> m[100001];
int main(){
int n;
scanf("%d",&n);
for(int i=2;i<=n;i++){
scanf("%d",&a[i]);
m[a[i]].push_back(i);
}
for(int i=n;i>0;i--){
dp[i][0]=1;
dp[i][1]=1;
for(int j=0;j<m[i].size();j++){
dp[i][1]*=dp[m[i][j]][0];
dp[i][0]*=(dp[m[i][j]][0]+dp[m[i][j]][1]);
dp[i][1]%=10007;
dp[i][0]%=10007;
}
}
printf("%d",(dp[1][0]+dp[1][1]-1)%10007);
return 0;
}

        终极大BOSS来了,难度瞬间提高,用搜索可写,但是大数据必定过不了,这题是老师说的基于MIT公司party发展过来,考试的时候写了个搜索上去,不知道拿了多少分,为了写这题,前边的都没时间了T_T,废话不多说,具体的来分析一下这道题(前边的题目都不分析了,但这题确实有难度):
         首先,可以去百度一下公司party那题,树状dp经典。
        然后回过头来看这题,在树状上做动态规划和这题的难点。
dp[i][0]代表第i个节点的人不去的方案数,dp[i][1]代表第i个节点去的方案数,
        然后难点来了, i节点的去于不去的方案数和什么有关呢,
仔细分析得到,如果i节点去了,那么他的下属都不能去,
那么dp[i][1]=dp[j][0]*dp[k][0]*dp[x][0]`````(j,k,x都是i节点的下属,为什么用的是乘法呢,这是应用到了乘法原理,下边还会用到)
        i节点去的情况分析完了,那么不去的情况是否也是那么简单呢,比赛之后我自己想了想
dp[i][0]=dp[j][0]*dp[k][1]+dp[j][1]*dp[k][1]+dp[j][0]*dp[k][1]  
(现在是假设i节点只有j和k两个子节点也就是下属,看出来什么规律没有,这就是乘法原理,当时我直接就把所有人都不去的情况没算进去,可是发现若是在多一个节点,这个多项式就要从现在的3项相加变成7项相加,再多两个呢,多更多呢,最后就一直拖到昨天都没想出来,然后今天学长启发了我,说可以把那个所有人都不去的情况先算在内,最后输出答案的时候减1就行了。)
这样,通过乘法原理,就简化出了上边代码中的 
dp[i][0]=(dp[j][0]+dp[j][1])*·········;,其中j为i的子节点。
    至此,递推式出来了 
                    dp[i][1]=dp[j][0]*dp[k][0]*dp[x][0]`````   j,k,x都是i节点的下属
                    dp[i][0]=(dp[j][0]+dp[j][1])*·········;,其中j为i的子节点。  
 但是不要忽略这题为什么叫树状dp,树状,还要基于树,
在算法中,图常常用邻接表来储存,这又是此题的一难点,用一个vector<int> m[N] 这样的数组来存储这棵数,m[i]的类型就是一个vector<int>  通俗了说m就是一个 vector<int> 型的数组,常常用这种结构来存储稀疏矩阵。m[i]这个的vector里边存的就是i节点的子节点
例如如果节点1子节点有 7和8,那么 m[1].size()=2,m[1][0]=7,m[1][1]=8(因为vector的特点是可以通过下标的方式取值,具有极大的便利),
最后,就是如上的代码,得到的递推式最终形式是 
dp[i][1]*=dp[m[i][j]][0];
dp[i][0]*=(dp[m[i][j]][0]+dp[m[i][j]][1]);  (其中m[i][j]就是i节点的子节点,j=0,1,2,3.....)
               然后把每个节点的初始值赋值成1,应为叶子节点时,没有下属,他去和不去只和他自己有关,去是一种方案,不去也是一种方案,而树枝节点的乘法运算也需要赋个初始值1,这样就干脆直接写进第一层循环,大功告成o(≧v≦)o~~,,on!不对,忘了说最后的答案是什么了,最后的方案总数应该是根节点去dp[root][1]和不去dp[root][0]之和,再减去所有人都不去的1种情况,
好了,然后别忘了模上10007,输出答案。 


总结:这次蓝桥杯校内赛虽然前几题还是很水,但是总体难度较之去年确实上升了不少,也无法预知省赛难度是否会提高,总之,先管自己学吧,学多少是多少,考试用到就是赚了,最后一题确实也符合了蓝桥往年惯例的风格,有难点,并且可以用简单的方法拿下部分的分,和决赛题风格非常相似,大概这题是去年决赛题的备胎吧,/抠鼻。 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值