第四届蓝桥杯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 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[] = 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 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 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 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
- */
<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
- */
<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;
- }
<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
- */
<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
- */
<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
- */