2013第四届蓝桥杯C/C++程序设计本科B组省赛试题解题报告

第一题

注意闰年不是简单判断4的倍数。闰年,四年一闰,百年不闰,四百又闰。
计算出来的答案是: 1799-07-16

#include <iostream>
#include <cstdio>
using namespace std;

const int MonJC[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
const int TMonJC[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};

class Date{
friend Date operator- (Date T,unsigned int n);
friend Date operator+ (Date T,unsigned int n);
friend istream& operator>> (istream& is,Date T);
friend ostream& operator<< (ostream& os,Date T);
public:
Date() {}
Date(int y,int m,int d):year(y),month(m),day(d) {}
bool check() //判断当前是否是闰年
{

if(!(year%400)) return true;//能被400整除
if(!(year%4))
{
if(!(year%100))
return false;
else
return true;
}
else
return false;
}
void Ty()
{

--year;
}
void Tm()
{

if(month==1)
{
month = 12;
Ty();
}
else
--month;
}
void Td()
{

if(day==1)
{
Tm();
if(check()) //闰年
day = TMonJC[month];
else
day = MonJC[month];
}
else
--day;
}
void Ay()
{

++year;
}
void Am()
{

if(month==12)
{
month = 1;
Ay();
}
else
++month;
}
void Ad()
{

if(month!=2)
{
if(day==MonJC[month])
{
day = 1;
Am();
}
else
++day;
}
else
if(check()) //闰年
{
if(day==TMonJC[month])
{
day = 1;
Am();
}
else
++day;
}
else
{
if(day==MonJC[month])
{
day = 1;
Am();
}
else
++day;
}
}
private:
int year,month,day;
};

Date operator- (Date T,unsigned int n)
{
while(n--)
T.Td();
return T;
}

Date operator+ (Date T,unsigned int n)
{
while(n--)
T.Ad();
return T;
}

istream& operator>> (istream& is,Date T)
{
char t;
is >> T.year >> t >> T.month >> t >> T.day;
return is;
}

ostream& operator<< (ostream& os,Date T)
{
cout << T.year << '/';
if(T.month<10)
cout << 0 << T.month << '/';
else
cout << T.month << '/';
if(T.day<10)
cout << 0 << T.day;
else
cout << T.day;
//printf("%02d/%02d/%02d",T.year,T.month,T.day);
return os;
}

int main(void)
{

Date *p = new Date();
Date base(1777,4,29);
cout << base+8113 << endl;
return 0;
}

第二题

暴力之,全排列算法都不用,直接上五重循环就可以了。
计算出的答案是: 142

#include<stdio.h>
int main()
{

int a,b,c,d,e;
int count = 0;
for(a=1; a<=9; ++a)
for(b=1; b<=9; ++b)
for(c=1; c<=9; ++c)
for(d=1; d<=9; ++d)
for(e=1; e<=9; ++e)
if(a!=b && a!=c && a!=d && a!=e &&
b!=c && b!=d && b!=e &&
c!=d && c!=e &&
d!=e &&
(a*10+b)*(c*100+d*10+e) == (a*100+d*10+b)*(c*10+e))
++count;
printf("%d",count);
}

第三题

假定先迈的是左脚,那么到达一层右脚落下的情况是0种,到一层左脚落下的情况是1种,到达二层左脚落下的情况是1种,到达二层右脚落下的情况是1种,之后到达第N层左脚落下的情况数是第N-1层右脚落下的情况数加上N-2层右脚落下的情况数,第N层右脚落下的情况数是第N-1层左脚落下的情况数加上N-2层左脚落下的情况数(这是基于第N层右脚落下,只能是从N-1层迈右脚走1或者从N-2层迈右脚走2的事实得到的结论)。

递推公式为:
arr[0][i] = arr[1][i-1] + arr[1][i-2]
arr[1][i] = arr[0][i-1] + arr[0][i-2]

计算结果为: 51167078

#include <stdio.h>
int main()
{

int i;
int arr[2][50];
/*[ ][N] 第N层状况*/
/*[0][N] 右脚落下,接下来迈出左脚*/
/*[1][N] 左脚落下,接下来迈出右脚*/
arr[0][1] = 0;
arr[1][1] = 1;
arr[0][2] = 1;
arr[1][2] = 1;
for(i=3; i<50; ++i)
{
arr[0][i] = arr[1][i-1] + arr[1][i-2];
arr[1][i] = arr[0][i-1] + arr[0][i-2];
}
printf("%d\n",arr[0][39]);
return 0;
}

第四题

模拟题目给出的连分式运算(有兴趣的朋友可以去试试其他的办法,比如利用(根号5-1)/2 - 1 去计算)
为了简单处理,用java的大数类写吧(不好好利用下java的大数,实在是浪费资源啊)。

因为不知道要计算到多少次才能到精度100…干脆就按OI的办法…10000-100000次吧…开个黑框让它慢慢算,反正比赛时间长,不怕它算不出来
计算小数点后101位: 0.61803 39887 49894 84820 45868 34365 63811 77203 09179 80576 28621 35448 62270 52604 62818 90244 97072 07204 18939 11374 8
四舍五入后答案为: 0.61803 39887 49894 84820 45868 34365 63811 77203 09179 80576 28621 35448 62270 52604 62818 90244 97072 07204 18939 11375

import java.util.Scanner;
import java.math.*;
import java.util.*;
public class Welcome
{

public static void main(String[] args)
{

int JD = 101;
BigDecimal b1 = new BigDecimal("1.000000");
BigDecimal b2 = new BigDecimal("1.000000");
for(int i = 0; i < 10000; ++i)
{
b2 = b1.divide(b2.add(new BigDecimal("1.0000000")),10000,BigDecimal.ROUND_HALF_UP);
}
System.out.println(b2.toString().substring(0,JD+2));
}
}

第五题

答案: *haystack++ != *needle++

第六题

答案: p++

第七题

#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int flag[100011] = {0};
int main()
{

string temp;
int T;
cin >> T;
getline(cin,temp); //读掉换行符
int chong=0,que=0;
int min=100000,max=0;
while(T--)
{
int id;
getline(cin,temp);
istringstream is(temp);
while(is >> id)
{
//cout << id << endl;
max = id>max?id:max;
min = id<min?id:min;
if(flag[id])
chong = id;
flag[id] = 1;
}
}
for(int i=min+1; i<max; ++i)
if(!flag[i])
{
que = i;
break;
}
cout << que << " "<< chong << endl;
return 0;
}

第八题

/*
12345678
o******o
*o*o***o 1 o**oo**o
**o****o 2 *o*oo**o
***o***o 3 **ooo**o
***o**o* 4 ****o**o
***o*o** 5 ***o***o
***oo*** 6 ***ooo*o
7 ***oo*oo
8 ***oo***
1 4 5 8
(4-1)+(8-5) (5-4)+(8-1)
1 6 8 11

*/


//一定有偶数个不同
//找出开始和目标中不同的对,最短的移动方案就很显而易见,就是依次将临近的不同对消除。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main(int argc, char const *argv[])
{

string start;
string aim;
vector<int> v;
int sum = 0;
cin >> start >> aim;
for(int i=0; i<(int)aim.size(); ++i)
if(aim[i] != start[i])
v.push_back(i);
for(int i=0; i*2<(int)v.size(); ++i)
sum += v[2*i+1] - v[2*i];
cout << sum << endl;
return 0;
}

第九题

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <time.h>
using namespace std;

int ans = 0;
int flag[10];
void dfs(int a,int b,int N)
{

int ac,bc;
ac = a;
bc = b;
if(a && b && b%(N-a)==0)
{
int tflag[10] = {0};
int c = b/(N-a);
int cc = c;
int ok = 1;
int sum = 0;
while(cc)
{
++sum;
if(cc%10==0 || flag[cc%10] || tflag[cc%10])
ok = 0;
else
tflag[cc%10] = 1;
cc /= 10;
}
while(ok && ac)
{
++sum;
ac /= 10;
}
while(ok && bc)
{
++sum;
bc /= 10;
}
if(ok && sum!=9)
ok = 0;
if(ok)
{
++ans;
//cout << a << " " << b << " " << c << endl;
//system("pause");
}
}
for(int i=1; i<=9; ++i)
{
if(!flag[i])
{
flag[i] = 1;
dfs(a,b*10+i,N);
flag[i] = 0;
}
}
}

int main()
{

int N;
cin >> N;
for(int i=1; i<N ; ++i)
{
memset(flag,0,sizeof(flag));
int ac = i;
int len = 0;
int ok = 1;
while(ac && ok)
{
++len;
if(flag[ac%10] || ac%10==0)
ok = 0;
else
flag[ac%10] = 1;
ac /= 10;
}
if(ok)
dfs(i,0,N);
}
cout << ans << endl;
//cout << clock()/CLOCKS_PER_SEC << endl;
return 0;
}

下载