第四届蓝桥杯C++本科B组解题报告
-转自themagickeyjianan的专栏
<1> 高斯日记
1799-7-16
- package JiaNan;
- import java.util.Calendar;
- import java.util.GregorianCalendar;
- public class GaoSiRiJi
- {
- static Calendar c = new GregorianCalendar(1791,12-1,15);
- public staticvoid main(String args[])
- {
- c.add(Calendar.DATE,8113-5343);
- System.out.println(c.get(Calendar.YEAR)+"-"+c.get(Calendar.MONTH)+"-"+c.get(Calendar.DATE));
- }
- }
- /*
- 1799-7-16 //注意:Java中月份是从0开始的,因此虽然输出是1799-6-16,但是要写成1799-7-16
- */
package JiaNan;
import java.util.Calendar;
import java.util.GregorianCalendar;
public class GaoSiRiJi
{
static Calendar c = new GregorianCalendar(1791,12-1,15);
public static void main(String args[])
{
c.add(Calendar.DATE,8113-5343);
System.out.println(c.get(Calendar.YEAR)+"-"+c.get(Calendar.MONTH)+"-"+c.get(Calendar.DATE));
}
}
/*
1799-7-16 //注意:Java中月份是从0开始的,因此虽然输出是1799-6-16,但是要写成1799-7-16
*/
<2>马虎的算式
142
方法1:高层循环,穷举法
- package JiaNan;
- public class MaHuDeSuanShi
- {
- static int kinds =0;
- static void f()
- {
- 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++)
- {
- int ab = 10*a + b;
- int cde = 100*c +10*d + e;
- int adb = 100*a + 10*d + b;
- int ce = 10*c + e;
- if(ab*cde != adb*ce)
- continue;
- int num[] = newint[10];
- num[a]++;
- num[b]++;
- num[c]++;
- num[d]++;
- num[e]++;
- int i;
- for(i = 1;i <=9;i++)
- {
- if(num[i] > 1)
- break;
- }
- if(i == 10)
- {
- //System.out.println(ab+"*"+cde+"="+adb+"*"+ce);
- kinds++;
- }
- }
- }
- public staticvoid main(String args[])
- {
- long start = System.nanoTime();
- f();
- System.out.println(kinds);
- long end = System.nanoTime();
- System.out.println("运行时间:"+(end-start)/Math.pow(10,9)+"s");
- }
- }
- /*
- 142
- 运行时间:0.010208086s
- */
package JiaNan;
public class MaHuDeSuanShi
{
static int kinds = 0;
static void f()
{
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++)
{
int ab = 10*a + b;
int cde = 100*c + 10*d + e;
int adb = 100*a + 10*d + b;
int ce = 10*c + e;
if(ab*cde != adb*ce)
continue;
int num[] = new int[10];
num[a]++;
num[b]++;
num[c]++;
num[d]++;
num[e]++;
int i;
for(i = 1;i <= 9;i++)
{
if(num[i] > 1)
break;
}
if(i == 10)
{
//System.out.println(ab+"*"+cde+"="+adb+"*"+ce);
kinds++;
}
}
}
public static void main(String args[])
{
long start = System.nanoTime();
f();
System.out.println(kinds);
long end = System.nanoTime();
System.out.println("运行时间:"+(end-start)/Math.pow(10, 9)+"s");
}
}
/*
142
运行时间:0.010208086s
*/
方法2:运用排列,进行穷举法
- package JiaNan;
- public class MaHuDeSuanShi
- {
- static int kinds =0;
- static int c[] =new int[6];//枚举排列
- static boolean vis[] =new boolean[10];//记录是否被访问
- static void check(int c[])
- {
- int ab = c[1]*10 + c[2];
- int cde = c[3]*100 + c[4]*10 + c[5];
- int adb = c[1]*100 + c[4]*10 + c[2];
- int ce = c[3]*10 + c[5];
- if(ab*cde == adb*ce)
- {
- //System.out.println(ab+"*"+cde+"="+adb+"*"+ce);
- kinds++;
- }
- }
- static void dfs(int start,int n)
- {
- if(start == 6)
- {
- check(c);
- return;
- }
- for(int i =1;i <= n;i++)
- {
- if(!vis[i])
- {
- c[start] = i;
- vis[i] = true;
- dfs(start+1,n);
- vis[i] = false;
- c[start] = 0;
- }
- }
- }
- public staticvoid main(String args[])
- {
- long start = System.nanoTime();
- dfs(1,9);
- System.out.println(kinds);
- long end = System.nanoTime();
- System.out.println("运行时间:"+(end-start)/Math.pow(10,9)+"s");
- }
- }
- /*
- 142
- 运行时间:0.002564503s
- */
- //备注:由此可见,排列是一种比较高效率的算法,大约效率是循环穷举的5倍。由此想到21位水仙花也是利用排列做的,效率都非常高
package JiaNan;
public class MaHuDeSuanShi
{
static int kinds = 0;
static int c[] = new int[6]; //枚举排列
static boolean vis[] = new boolean[10]; //记录是否被访问
static void check(int c[])
{
int ab = c[1]*10 + c[2];
int cde = c[3]*100 + c[4]*10 + c[5];
int adb = c[1]*100 + c[4]*10 + c[2];
int ce = c[3]*10 + c[5];
if(ab*cde == adb*ce)
{
//System.out.println(ab+"*"+cde+"="+adb+"*"+ce);
kinds++;
}
}
static void dfs(int start,int n)
{
if(start == 6)
{
check(c);
return;
}
for(int i = 1;i <= n;i++)
{
if(!vis[i])
{
c[start] = i;
vis[i] = true;
dfs(start+1,n);
vis[i] = false;
c[start] = 0;
}
}
}
public static void main(String args[])
{
long start = System.nanoTime();
dfs(1,9);
System.out.println(kinds);
long end = System.nanoTime();
System.out.println("运行时间:"+(end-start)/Math.pow(10, 9)+"s");
}
}
/*
142
运行时间:0.002564503s
*/
//备注:由此可见,排列是一种比较高效率的算法,大约效率是循环穷举的5倍。由此想到21位水仙花也是利用排列做的,效率都非常高
<3>39台阶
51167078
- package JiaNan;
- public class _39TaiJie
- {
- static int kinds =0;
- static int c[] =new int[40];//最多走39步
- static int choice[] =new int[]{1,2};
- static void dfs(int start,int n)
- {
- if(n <= 0)
- {
- if(n==0 && start%2==0)
- {
- kinds++;
- }
- return;
- }
- for(int i =0;i <= 1;i++)
- {
- c[start] = choice[i];
- dfs(start+1,n-choice[i]); //对比上一题,总结何时需要恢复:当要避免重复时就需要vis数组记录一下避免重复,还有韩信走马分酒问题也是用了vis
- }
- }
- public staticvoid main(String args[])
- {
- long start = System.nanoTime();
- dfs(0,39);
- System.out.println(kinds);
- long end = System.nanoTime();
- System.out.println("运行时间:"+(end-start)/Math.pow(10,9)+"s");
- }
- }
- /*
- 51167078
- 运行时间:5.390165205s
- */
package JiaNan;
public class _39TaiJie
{
static int kinds = 0;
static int c[] = new int[40]; //最多走39步
static int choice[] = new int[]{1,2};
static void dfs(int start,int n)
{
if(n <= 0)
{
if(n==0 && start%2==0)
{
kinds++;
}
return;
}
for(int i = 0;i <= 1;i++)
{
c[start] = choice[i];
dfs(start+1,n-choice[i]); //对比上一题,总结何时需要恢复:当要避免重复时就需要vis数组记录一下避免重复,还有韩信走马分酒问题也是用了vis
}
}
public static void main(String args[])
{
long start = System.nanoTime();
dfs(0,39);
System.out.println(kinds);
long end = System.nanoTime();
System.out.println("运行时间:"+(end-start)/Math.pow(10, 9)+"s");
}
}
/*
51167078
运行时间:5.390165205s
*/
<4>黄金连分数
0.6180339887498948482045868343656381177203091798057628621354486227052604628189024497050372347293136948
算法思想:在用递归f(n) = 1/(1+f(n-1));求解的过程中一直精确到300位,在最后输出时,再四舍五入到100位,这样将精度损失避免到最小
- package JiaNan;
- import java.math.BigDecimal;
- import java.math.MathContext;
- public class HuangJinLianFenShu
- {
- static BigDecimal f(int n)
- {
- if(n == 1)
- return BigDecimal.valueOf(1.0);
- return BigDecimal.valueOf(1.0).divide(new BigDecimal(BigDecimal.valueOf(1.0).add(f(n-1)).toString()),new MathContext(300));
- }
- public staticvoid main(String args[])
- {
- long start = System.nanoTime();
- BigDecimal des = new BigDecimal(f(200).toString(),new MathContext(100));
- System.out.println(des);
- long end = System.nanoTime();
- System.out.println("运行时间:"+(end-start)/Math.pow(10,9)+"s");
- }
- }
- /*
- 0.6180339887498948482045868343656381177203091798057628621354486227052604628189024497050372347293136948
- 运行时间:0.08024721s
- */
package JiaNan;
import java.math.BigDecimal;
import java.math.MathContext;
public class HuangJinLianFenShu
{
static BigDecimal f(int n)
{
if(n == 1)
return BigDecimal.valueOf(1.0);
return BigDecimal.valueOf(1.0).divide(new BigDecimal(BigDecimal.valueOf(1.0).add(f(n-1)).toString()),new MathContext(300));
}
public static void main(String args[])
{
long start = System.nanoTime();
BigDecimal des = new BigDecimal(f(200).toString(),new MathContext(100));
System.out.println(des);
long end = System.nanoTime();
System.out.println("运行时间:"+(end-start)/Math.pow(10, 9)+"s");
}
}
/*
0.6180339887498948482045868343656381177203091798057628621354486227052604628189024497050372347293136948
运行时间:0.08024721s
*/
<5>前缀判断
*haystack++ != *needle++
- #include<iostream>
- using namespace std;
- char* prefix(char* haystack_start,char* needle_start)
- {
- char* haystack = haystack_start;
- char* needle = needle_start;
- while(*haystack && *needle)
- {
- if(*haystack++ != *needle++)
- return NULL; //填空位置
- }
- if(*needle)
- return NULL;
- return haystack_start;
- }
- void main()
- {
- cout<<prefix("abc123","abc")<<endl;
- }
- /*
- abc123
- */
#include<iostream>
using namespace std;
char* prefix(char* haystack_start, char* needle_start)
{
char* haystack = haystack_start;
char* needle = needle_start;
while(*haystack && *needle)
{
if(*haystack++ != *needle++)
return NULL; //填空位置
}
if(*needle)
return NULL;
return haystack_start;
}
void main()
{
cout<<prefix("abc123","abc")<<endl;
}
/*
abc123
*/
<6>三部排序
p++
- #include<iostream>
- using namespace std;
- void sort3p(int* x,int len)
- {
- int p = 0;
- int left = 0;
- int right = len-1;
- while(p<=right)
- {
- if(x[p]<0)
- {
- int t = x[left];
- x[left] = x[p];
- x[p] = t;
- left++;
- p++;
- }
- else if(x[p]>0)
- {
- int t = x[right];
- x[right] = x[p];
- x[p] = t;
- right--;
- }
- else
- {
- p++; //填空位置
- }
- }
- }
- void main()
- {
- int x[] = {25,18,-2,0,16,-5,33,21,0,19,-16,25,-3,0};
- sort3p(x,sizeof(x)/sizeof(x[0]));
- for(int i = 0;i <sizeof(x)/sizeof(x[0]);i++)
- cout<<x[i]<<" ";
- cout<<endl;
- }
- /*
- -3 -2 -16 -5 0 0 0 21 19 33 25 16 18 25
- */
#include<iostream>
using namespace std;
void sort3p(int* x, int len)
{
int p = 0;
int left = 0;
int right = len-1;
while(p<=right)
{
if(x[p]<0)
{
int t = x[left];
x[left] = x[p];
x[p] = t;
left++;
p++;
}
else if(x[p]>0)
{
int t = x[right];
x[right] = x[p];
x[p] = t;
right--;
}
else
{
p++; //填空位置
}
}
}
void main()
{
int x[] = {25,18,-2,0,16,-5,33,21,0,19,-16,25,-3,0};
sort3p(x,sizeof(x)/sizeof(x[0]));
for(int i = 0;i < sizeof(x)/sizeof(x[0]);i++)
cout<<x[i]<<" ";
cout<<endl;
}
/*
-3 -2 -16 -5 0 0 0 21 19 33 25 16 18 25
*/
<7>错误票据
- #include<iostream>
- #include<vector>
- using namespace std;
- void f(int N)
- {
- if(N == 0)
- return;
- vector<int> v;
- int row = 0;
- while(1)
- {
- int num;
- cin>>num;
- v.push_back(num);
- if(cin.get() == '\n')
- {
- if(++row == N)
- break;
- }
- }
- int min = v[0],max = v[0];
- for(int i = 1;i <= v.size()-1;i++)
- {
- if(v[i] < min)
- min = v[i];
- if(v[i] > max)
- max = v[i];
- }
- int* len = new int[max];
- for(int m = 0;m < max;m++)
- {
- len[m] = 0;
- }
- for(int j = 0;j <= v.size()-1;j++)
- {
- len[v[j]]++;
- }
- for(int k = min;k <= max;k++)
- {
- if(len[k] == 0)
- cout<<k<<" ";
- if(len[k] > 1)
- cout<<k<<" ";
- }
- }
- void main()
- {
- int N;
- cin>>N;
- f(N);
- cout<<endl;
- }
#include<iostream>
#include<vector>
using namespace std;
void f(int N)
{
if(N == 0)
return;
vector<int> v;
int row = 0;
while(1)
{
int num;
cin>>num;
v.push_back(num);
if(cin.get() == '\n')
{
if(++row == N)
break;
}
}
int min = v[0],max = v[0];
for(int i = 1;i <= v.size()-1;i++)
{
if(v[i] < min)
min = v[i];
if(v[i] > max)
max = v[i];
}
int* len = new int[max];
for(int m = 0;m < max;m++)
{
len[m] = 0;
}
for(int j = 0;j <= v.size()-1;j++)
{
len[v[j]]++;
}
for(int k = min;k <= max;k++)
{
if(len[k] == 0)
cout<<k<<" ";
if(len[k] > 1)
cout<<k<<" ";
}
}
void main()
{
int N;
cin>>N;
f(N);
cout<<endl;
}
<8>翻硬币
- #include<iostream>
- using namespace std;
- int f(char sorc[],char dest[])
- {
- int minTimes = 0;//最少翻转次数
- char* p = sorc;
- char* q = dest;
- while(*p=='o' || *p=='*')
- {
- if(*p != *q)
- {
- switch(*p)
- {
- case '*':
- *p = 'o';
- if(*(p+1) == '*')
- {
- *(p+1) = 'o';
- }
- else
- {
- if(*(p+1) == 'o')
- *(p+1) = '*';
- }
- p++;
- q++;
- minTimes++;
- break;
- case 'o':
- *p = '*';
- if(*(p+1) == '*')
- {
- *(p+1) = 'o';
- }
- else
- {
- if(*(p+1) == 'o')
- *(p+1) = '*';
- }
- p++;
- q++;
- minTimes++;
- break;
- }
- }
- else //设计程序,当你考虑到相等的情况,就要考虑到不等的情况
- {
- p++;
- q++;
- }
- }
- return minTimes;
- }
- void main()
- {
- char sroc[30];
- char dest[30];
- cin>>sroc>>dest;
- cout<<f(sroc,dest)<<endl;
- }
- /*
- **********
- o****o****
- 5
- */
#include<iostream>
using namespace std;
int f(char sorc[],char dest[])
{
int minTimes = 0; //最少翻转次数
char* p = sorc;
char* q = dest;
while(*p=='o' || *p=='*')
{
if(*p != *q)
{
switch(*p)
{
case '*':
*p = 'o';
if(*(p+1) == '*')
{
*(p+1) = 'o';
}
else
{
if(*(p+1) == 'o')
*(p+1) = '*';
}
p++;
q++;
minTimes++;
break;
case 'o':
*p = '*';
if(*(p+1) == '*')
{
*(p+1) = 'o';
}
else
{
if(*(p+1) == 'o')
*(p+1) = '*';
}
p++;
q++;
minTimes++;
break;
}
}
else //设计程序,当你考虑到相等的情况,就要考虑到不等的情况
{
p++;
q++;
}
}
return minTimes;
}
void main()
{
char sroc[30];
char dest[30];
cin>>sroc>>dest;
cout<<f(sroc,dest)<<endl;
}
/*
**********
o****o****
5
*/
<9>带分数
- #include<iostream>
- #include<ctime>
- using namespace std;
- int N;
- int c[10]; //记录1-9数字的全排列
- bool vis[10]; //记录空间节点是否被访问过
- int kinds = 0;
- //
- int GetWeiShu(int N)//得到一个指定数字的位数
- {
- int weishu = 0;
- while(N > 0)
- {
- weishu++;
- N /= 10;
- }
- return weishu;
- }
- /
- int GetNum(int start,int end)
- {
- int sum = 0;
- for(int i = start;i <= end;i++)
- {
- sum = sum*10 + c[i];
- }
- return sum;
- }
- /
- void check(int N,int* c)
- {
- for(int i = 1;i <= GetWeiShu(N);i++)
- {
- int midMinLen = (9-i+1)/2;
- for(int j = i+midMinLen;j <= 8;j++)
- {
- int X = GetNum(1,i);
- int Y = GetNum(i+1,j);
- int Z = GetNum(j+1,9);
- if(Y%Z==0 && N==X+Y/Z)
- {
- //cout<<N<<"="<<X<<"+"<<Y<<"/"<<Z<<endl;
- kinds++;
- }
- }
- }
- }
- /
- void dfs(int start,int n)
- {
- if(start == 10)
- {
- check(N,c);
- return;
- }
- for(int i = 1;i <= n;i++)
- {
- if(!vis[i])
- {
- c[start] = i;
- vis[i] = true;
- dfs(start+1,n);
- vis[i] = false;
- }
- }
- }
- void main()
- {
- double start = clock();
- cin>>N;
- dfs(1,9);
- double end = clock();
- cout<<"一共有:"<<kinds<<"种情况"<<endl;
- cout<<"运行时间:"<<(end-start)/CLOCKS_PER_SEC<<"s"<<endl;
- }
- /*
- 100
- 100=3+69258/714
- 100=81+5643/297
- 100=81+7524/396
- 100=82+3546/197
- 100=91+5742/638
- 100=91+5823/647
- 100=91+7524/836
- 100=94+1578/263
- 100=96+1428/357
- 100=96+1752/438
- 100=96+2148/537
- 一共有:11种情况
- 运行时间:8.41s
- 105
- 105=72+6534/198
- 105=87+3456/192
- 105=87+9612/534
- 105=92+5681/437
- 105=92+6734/518
- 105=98+3647/521
- 一共有:6种情况
- 运行时间:3.512s
- */
#include<iostream>
#include<ctime>
using namespace std;
int N;
int c[10]; //记录1-9数字的全排列
bool vis[10]; //记录空间节点是否被访问过
int kinds = 0;
//
int GetWeiShu(int N) //得到一个指定数字的位数
{
int weishu = 0;
while(N > 0)
{
weishu++;
N /= 10;
}
return weishu;
}
/
int GetNum(int start,int end)
{
int sum = 0;
for(int i = start;i <= end;i++)
{
sum = sum*10 + c[i];
}
return sum;
}
/
void check(int N,int* c)
{
for(int i = 1;i <= GetWeiShu(N);i++)
{
int midMinLen = (9-i+1)/2;
for(int j = i+midMinLen;j <= 8;j++)
{
int X = GetNum(1,i);
int Y = GetNum(i+1,j);
int Z = GetNum(j+1,9);
if(Y%Z==0 && N==X+Y/Z)
{
//cout<<N<<"="<<X<<"+"<<Y<<"/"<<Z<<endl;
kinds++;
}
}
}
}
/
void dfs(int start,int n)
{
if(start == 10)
{
check(N,c);
return;
}
for(int i = 1;i <= n;i++)
{
if(!vis[i])
{
c[start] = i;
vis[i] = true;
dfs(start+1,n);
vis[i] = false;
}
}
}
void main()
{
double start = clock();
cin>>N;
dfs(1,9);
double end = clock();
cout<<"一共有:"<<kinds<<"种情况"<<endl;
cout<<"运行时间:"<<(end-start)/CLOCKS_PER_SEC<<"s"<<endl;
}
/*
100
100=3+69258/714
100=81+5643/297
100=81+7524/396
100=82+3546/197
100=91+5742/638
100=91+5823/647
100=91+7524/836
100=94+1578/263
100=96+1428/357
100=96+1752/438
100=96+2148/537
一共有:11种情况
运行时间:8.41s
105
105=72+6534/198
105=87+3456/192
105=87+9612/534
105=92+5681/437
105=92+6734/518
105=98+3647/521
一共有:6种情况
运行时间:3.512s
*/
<10>连号区间数
- #include<iostream>
- #include<vector>
- using namespace std;
- vector<int> v;
- int kinds = 0;
- //
- int GetMin(const vector<int> & v,int start,int end)
- {
- int min = v[start];
- for(int i = start;i <= end;i++)
- {
- if(v[i] < min)
- min = v[i];
- }
- return min;
- }
- //
- int GetMax(const vector<int> & v,int start,int end)
- {
- int max = v[start];
- for(int i = start;i <= end;i++)
- {
- if(v[i] > max)
- max = v[i];
- }
- return max;
- }
- //
- void f(const vector<int> & v)
- {
- for(int i = 0;i < v.size();i++)
- for(int j = 0;j < v.size();j++)
- {
- int min = GetMin(v,i,j);
- int max = GetMax(v,i,j);
- if(j-i+1 == max-min+1)
- {
- kinds++;
- }
- }
- }
- void main()
- {
- int N;
- cin>>N;
- while(N--)
- {
- int num;
- cin>>num;
- v.push_back(num);
- }
- f(v);
- cout<<kinds<<endl;
- }
- /*
- 5
- 3 4 2 5 1
- 9
- */