• 第五届蓝桥杯校内选拔赛


    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 ", get_word_num(buf));
      return 0;
    }

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    using namespace std;
    
    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 (tag == 1 && *p != ' ') { n++; tag = 0; }   //若果当前不是' '并且上一个是' '
    	}
    
    	return n;
    }
    
    int main()
    {
    	char buf[1000];
    	fgets(buf, 1000, stdin);
    
    	printf("%d
    ", get_word_num(buf));
    	return 0;
    }
    

     

    2>小数运算

    1/1 + 1/2 + 1/3 + 1/4 + ... 在数学上称为调和级数。

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

    但是,它发散的很慢:

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

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

    请填写这个整数。

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

    #include<iostream>
    #include<algorithm>
    using namespace std;
    int main() {
    	double cnt = 0;
    	for (int i = 1; i < 10000000; i++) {
    		cnt += 1.0 / (double)i;
    		if (cnt >= 15.0) {
    			cout << i << "
    ";
    			break;
    		}
    	}
    	return 0;
    }
    //输出:1835421
    

     

    3> 小数运算+四舍五入/小数二分

    如果x的x次幂结果为10(参见【图1.png】),你能计算出x的近似值吗?

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

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

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

    【图1.png】:

    方法一:小数二分

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    using namespace std;
    
    void erf() {//方法一
    	double le = 2.0, ri = 3.0, mid;
    	for (int i = 1; i<200; i++)//小数二分搜索
    		if (le< ri) {
    			mid = (le + ri) / 2.0;
    			if (pow(mid, mid) >= 9.99999999&&pow(mid, mid) <= 10.00000001)break;
    			else if (pow(mid, mid) < 10.0)le = mid;
    			else ri = mid;
    		}
    	printf("%.10f
    ", mid);
    }
    
    
    int main() {
    	erf();
    	return 0;
    }
    // 结果:2.5061841458   答案保留六位即可
    

      方法二:枚举

    #include<iostream>
    #include<algorithm>
    #include<math.h>
    using namespace std;
    
    void so()
    {
    	double x;
    	for (x = 2.0; x<3.0; x += 0.00000001)//枚举
    	{
    		if (abs(pow(x, x) - 10.0)<0.000001)
    			printf("%.10f
    ", x);
    	}
    }
    
    int main() {
    	so();
    	return 0;
    }
    // 结果:
    //2.5061840969
    //2.5061841069
    //2.5061841169
    //2.5061841269
    //2.5061841369
    //2.5061841469
    //2.5061841569
    //2.5061841669
    //2.5061841769
    //2.5061841869
    //2.5061841969
    //答案保留六位即可

     

    4> dfs/全排列

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

    17126425374635

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

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

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

    方法一:dfs

    #include<iostream>
    #include<algorithm>
    using namespace std;
    int a[16], book[8];//a[i]代表第i个数 book[i]代表i是否用过
    void dfs(int ans) {//ans代表当前第几个
    	if (ans == 15) {
    		for (int i = 1; i < 15; i++)
    			cout << a[i];
    		cout << "
    ";
    		return;
    	}
    	if (a[ans] != 0)dfs(ans + 1);
    	for (int i = 1; i < 7; i++) {//依次枚举当前放数字几
    		if (book[i] == 0 && a[ans] == 0 && a[ans + i + 1] == 0) {
    			a[ans] = a[ans + i + 1] = i;//放入i
    			book[i] = 1;//标记i已用
    
    			dfs(ans + 1);
    
    			book[i] = 0;
    			a[ans] = a[ans + i + 1] = 0;
    		}
    
    	}
    }
    int main() {
    	book[4] = 1;
    	book[7] = 1;
    	a[1] = a[9] = 7;
    	a[2] = a[7] = 4;//搜索前一定要把标记的先标记上
    
    	dfs(3);
    	return 0;
    }
    //74151643752362
    

      方法二:全排列

    #include<iostream>
    #include<algorithm>
    using namespace std;
     
    void p() {//全排列方法   速度慢
        int b[15] = { 7,4,1,1,2,2,4,3,7,3,5,5,6,6 };//把数都导入
        bool book2[15];
        while (next_permutation(b + 2, b + 14)) {//全排列函数
            memset(book2, 0, sizeof(book2));
            int i;
            for (i = 0; i < 14; i++) {//枚举每个位置
                if (book2[i])continue;
                else {
                    if (b[i] == b[i + b[i] + 1])
                        book2[i + b[i] + 1] = true;
                    else break;
                }
            }
            if (i == 14) {//满足条件就输出
                for (i = 0; i < 14; i++)
                    cout << b[i];
                cout << "
    ";
                break;
            }
        }
    }
    int main() {
        p();
        return 0;
    }
    //74151643752362
    

      

    5>思维

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

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

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

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

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

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

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


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

    #include <iostream>
    #include <algorithm>
    #include<math.h>
    using namespace std;
    #define ll long long
    ll a[100001];
    
    int main()
    {
    	ll n,x,y,cnt = 0;
    	cin >> n;
    	for (int i = 1; i<n / sqrt(2); i++)//根据三角形构成条件,缩小范围
    	{
    		x = i*i;
    		y = sqrt(n*n - x);
    		if (x+y*y== n*n)cnt++;
    	}
    	cout << cnt << endl;
    }
    

     

    6>dfs

    你一定听说过“数独”游戏。
    玩家需要根据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

    #include<iostream>
    #include<algorithm>
    #include<string>
    using namespace std;
    char t[20][20];
    //a:每个格的数  kx[][]:记录横向数是否已用  ky[][]:记录横向数是否已用  kj[][]:记录九宫格是否已用
    int a[20][20], kx[20][20], ky[20][20],kj[20][20],ans=0;
    
    void dfs(int x, int y) {
    	//cout << "(" << x << "," << y << ")" << " ";
    	if (ans)return;
    	if (x == 10) {
    		ans = 1;
    		for (int i = 1; i < 10; i++) {
    			for (int j = 1; j < 10; j++)
    				cout << a[i][j];
    			cout << "
    ";
    		}
    		return;
    	}
    	if (a[x][y] == 0) {
    		for (int i = 1; i<10; i++)
    			if (kx[x][i] == 0 && ky[y][i] == 0&& kj[(x - 1) / 3 * 3 + (y + 2) / 3][i] ==0) {
    				kj[(x - 1) / 3 * 3 + (y + 2) / 3][i] = 1;
    				kx[x][i] = 1;
    				ky[y][i] = 1;
    				a[x][y] = i;
    
    				if (y == 9)dfs(x + 1, 1);
    				else dfs(x, y + 1);
    
    				a[x][y] = 0;
    				kx[x][i] = 0;
    				ky[y][i] = 0;
    				kj[(x - 1) / 3 * 3 + (y + 2) / 3][i] = 0;
    			}
    	}
    	else {
    		if (y == 9)dfs(x + 1, 1);
    		else dfs(x, y + 1);
    	}
    	return;
    }
    int main() {
    	for (int i = 1; i < 10; i++) {
    		for (int j = 1; j < 10; j++) {
    			cin >> t[i][j];
    			a[i][j] = t[i][j] - '0';
    			if (a[i][j] != 0) {
    				kx[i][a[i][j]] = 1;
    				ky[j][a[i][j]] = 1;
    				kj[(i-1)/3*3+(j+2)/3][a[i][j]] = 1;//巧妙地是这里,将九大块刚好编号为1~9
    			}
    		}
    
    	}
    	cout << "
    ";
    	dfs(1, 1);
    	return 0;
    }
    

      

    7:dp

      参考博文:https://blog.csdn.net/dodd9199/article/details/41916121

      这位博主说的很详细,Orz

    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

    #include <iostream>
    #include<algorithm>
    #include<vector>
    using namespace std;
    int n,dp[100010][2],t;
    vector<int>v[100010];
    int main() {
    	ios::sync_with_stdio(0);
    	cin.tie(0), cout.tie(0);
    	cin >> n;
    	for (int i = 2; i <= n; i++)
    	{
    		cin >> t;
    		v[t].push_back(i);
    	}
    	for (int i = n; i > 0; i--) {    //从下向上
    		dp[i][0] = 1;         //初始化
    		dp[i][1] = 1;         //初始化
    		for (int j = 0; j < v[i].size(); j++) {
    			dp[i][0] *= (dp[v[i][j]][0] + dp[v[i][j]][1]);//下级(去+不去) 的累乘
    			dp[i][1] *= dp[v[i][j]][0];//下级(不去)的累乘
    			dp[i][0] %= 10007;
    			dp[i][1] %= 10007;
    		}
    	}
    	cout << dp[1][1] + dp[1][0] - 1 << "
    ";//减去都不去的情况
    	return 0;
    }
    

     

  • 相关阅读:
    多线程
    泛型
    枚举、注解
    重写comparater比较器
    Arrays工具类和Collections工具类
    重写equals和hashCode的方法
    遍历集合的方法
    关键字总结
    having 的用法
    HTTP协议
  • 原文地址:https://www.cnblogs.com/52dxer/p/10402636.html
Copyright © 2020-2023  润新知