C/C++ 第六届蓝桥杯大赛个人赛校内选拔活动(大学A组) 题解

文章目录

    • 1. 第一题
    • 2. 第二题
    • 3. 第三题
    • 4. 第四题
    • 5. 第五题
    • 6. 第六题
    • 7. 第七题

题目 类型
第一题 代码填空
第二题 结果填空
第三题 结果填空
第四题 结果填空
第五题 程序设计
第六题 程序设计
第七题 程序设计

1. 第一题

  • 本题总分:10分

  • 问题描述
    一个串的子串是指该串的一个连续的局部。如果不要求连续,则可称为它的子序列。
    比如对串: “abcdefg” 而言,“ab”,“abd”,“bdef” 等都是它的子序列。
    特别地,一个串本身,以及空串也是它的子序列。

    对两个串而言,可以有许多的共同的子序列,我们关心的是:它们所共同拥有的长度最大的子序列是多长。以下代码实现了这个问题的求解。请填写划线部分缺失的代码。

    inline max(int a, int b)
    {
    	return a>b?a:b;
    }
    
    int f(char* x, char* y)
    {
    	if(strlen(x)==0) return 0;
    	if(strlen(y)==0) return 0;
    	
    	if(*x == *y) return f(x+1, y+1) + 1;
    	
    	return max( ______________________ );
    }
    
    int main()
    {
    	printf("%d\n", f("ac","abcd")); //2
    	printf("%d\n", f("acebbcde1133","xya33bc11de")); //5
    	return 0;
    }
    
  • 注意
    只填写划线部分缺少的内容,不要填写任何多余的符号或注释、说明等。例如,不要填写已经给出的小括号。


  • 解析
    要么串x扔掉一个,要么串y扔掉一个,然后取这两者之间的最大值即可

  • 答案

    f(x, y + 1), f(x + 1, y)
    

2. 第二题

  • 本题总分:6分

  • 问题描述
    历史上有许多计算圆周率pai的公式,其中,格雷戈里和莱布尼茨发现了下面的公式:

    pai = 4*(1-1/3+1/5-1/7 …)

    参见下图

    C/C++ 第六届蓝桥杯大赛个人赛校内选拔活动(大学A组) 题解_第1张图片

    这个公式简单而优美,但美中不足,它收敛的太慢了。
    如果我们四舍五入保留它的两位小数,那么:

    累积了1项和是:4.00
    累积了2项和是:2.67
    累积了3项和是:3.47

    请你写出它累积了100项的和是多少(四舍五入到小数后两位)。

  • 注意
    只填写该小数本身,不要填写任何多余的说明或解释文字。


  • 解析

    #include
    using namespace std;
    
    //保留两位小数,四舍五入
    double func(double n)
    {
    	int last = (int)(n * 1000) % 10;
    	if (last >= 5) n = double((int)(n * 100) + 1.0) / 100.0;
    	else n = double((int)(n * 100)) / 100.0;
    	return n;
    }
    
    int main()
    {
    	double sum = 0.0;
    	int last;
    	for (int i = 1; i <= 100; i++)
    	{
    		double num = 4.0 / (i * 2.0 - 1.0);
    		num = func(num);//四舍五入
    
    		if (i % 2 != 0) sum += num;
    		else sum -= num;
    	}
    	cout << sum;
    	return 0;
    }
    
  • 答案
    3.15


3. 第三题

  • 本题总分:8分

  • 问题描述
    如果x的x次幂结果为10(参见下图),你能计算出x的近似值吗?

    C/C++ 第六届蓝桥杯大赛个人赛校内选拔活动(大学A组) 题解_第2张图片

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

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

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


  • 解析

    #include
    #include
    using namespace std;
    
    int main()
    {
    	double x = 2.0;
    	double min = 10.0;
    	double ans = 2.0;
    	for (x = 2.0; x < 3.0; x += 0.000001)
    	{
    		double num = pow(x, x);
    		if (fabs(num - 10.0) < min)
    		{
    			min = fabs(num - 10.0);
    			ans = x;
    		}
    	}
    	cout << fixed << setprecision(7) << ans;
    	return 0;
    }
    
  • 答案
    2.506184


4. 第四题

  • 本题总分:13分

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

    17126425374635

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

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

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


  • 解析

    #include
    #include
    using namespace std;
    bool vis[8];
    
    bool check(string s)
    {
    	if (s[0] != '7' || s[1] != '4') return false;
    	if (s[8] != '7' || s[6] != '4') return false;
    	for (int i = 1; i <= 7; i++)
    	{
    		for (int j = 2; j < 14; j++)
    		{
    			if (!vis[i] && s[j] == char(i + '0'))
    			{
    				vis[i] = 1;
    				if (s[j + i + 1] != char(i + '0')) return false;
    			}
    		}
    	}
    	return true;
    }
    
    int main()
    {
    	string s = "11223344556677";
    	do
    	{
    		memset(vis, 0, sizeof(vis));
    		vis[4] = vis[7] = 1;
    		if (check(s)) cout << s << endl;
    	} while (next_permutation(s.begin(), s.end()));
    	return 0;
    }
    
  • 答案
    74151643752362


5. 第五题

  • 本题总分:11分

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

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

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

  • 输入格式
    输入一个整数 n (0

  • 输出格式
    要求输出一个整数,表示满足条件的直角三角形个数。

  • 样例输入
    5

  • 样例输出
    1

  • 样例输入
    100

  • 样例输出
    2

  • 样例输入
    3

  • 样例输出
    0

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

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

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

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

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


  • 答案

    #include
    using namespace std;
    
    int main()
    {
    	int ans = 0;
    	long long n;
    	cin >> n;
    	long long n2 = n * n;
    	for (long long i = 1; i < n; i++)
    	{
    		long long j = sqrt(n2 - i * i);
    		if (j * j + i * i == n2) ans++;
    	}
    	cout << ans / 2;
    	return 0;
    }
    

6. 第六题

  • 本题总分:20分

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

    C/C++ 第六届蓝桥杯大赛个人赛校内选拔活动(大学A组) 题解_第3张图片

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

    本图的数字据说是芬兰数学家花了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 , 不能通过工程设置而省略常用头文件。

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


  • 答案

    #include
    using namespace std;
    int map[10][10];
    
    int range(int n)
    {
    	if (n >= 1 && n <= 3) return 1;
    	else if (n >= 4 && n <= 6) return 4;
    	else return 7;
    }
    
    bool check(int x, int y, int n)
    {
    	//检查行列
    	for (int i = 1; i <= 9; i++)
    	{
    		if (map[x][i] == n || map[i][y] == n) return false;
    	}
    
    	//检查九宫格
    	int r = range(x);
    	int c = range(y);
    	for (int i = r; i <= r + 2; i++)
    	{
    		for (int j = c; j <= c + 2; j++)
    		{
    			if (map[i][j] == n) return false;
    		}
    	}
    	return true;
    }
    
    void dfs(int x, int y)
    {
    	//完成填数,输出
    	if (y > 9)
    	{
    		for (int i = 1; i <= 9; i++)
    		{
    			for (int j = 1; j <= 9; j++)
    			{
    				cout << map[i][j];
    			}
    			cout << endl;
    		}
    		exit(0);
    	}
    
    	if (map[x][y] == 0)
    	{
    		for (int i = 1; i <= 9; i++)
    		{
    			if (check(x, y, i))
    			{
    				map[x][y] = i;
    				dfs((x + 1) % 10, y + (x + 1) / 10);
    				map[x][y] = 0;
    			}
    		}
    	}
    	else dfs((x + 1) % 10, y + (x + 1) / 10);
    
    }
    
    int main()
    {
    	//输入
    	for (int i = 1; i <= 9; i++)
    	{
    		string s;
    		cin >> s;
    		for (int j = 0; j < 9; j++)
    		{
    			if (s[j] != '0') map[i][j + 1] = s[j] - '0';
    		}
    	}
    
    	dfs(1, 1);
    
    	return 0;
    }
    

7. 第七题

  • 本题总分:32分

  • 问题描述
    G将军有一支训练有素的军队,这个军队除开G将军外,每名士兵都有一个直接上级(可能是其他士兵,也可能是G将军)。现在G将军将接受一个特别的任务,需要派遣一部分士兵(至少一个)组成一个敢死队,为了增加敢死队队员的独立性,要求如果一名士兵在敢死队中,他的直接上级不能在敢死队中。
    请问,G将军有多少种派出敢死队的方法。注意,G将军也可以作为一个士兵进入敢死队。

  • 输入格式
    输入的第一行包含一个整数n,表示包括G将军在内的军队的人数。军队的士兵从1至n编号,G将军编号为1。
    接下来n-1个数,分别表示编号为2, 3, …, n的士兵的直接上级编号,编号i的士兵的直接上级的编号小于i。

  • 输出格式
    输出一个整数,表示派出敢死队的方案数。由于数目可能很大,你只需要输出这个数除10007的余数即可。

  • 样例输入
    3
    1 1

  • 样例输出
    4

  • 样例说明
    这四种方式分别是:
    1.选1;
    2.选2;
    3.选3;
    4.选2, 3。

  • 样例输入
    7
    1 1 2 2 3 3

  • 样例输出
    40

  • 数据规模与约定
    对于20%的数据,n ≤ 20;
    对于40%的数据,n ≤ 100;
    对于100%的数据,1 ≤ n ≤ 100000。

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

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

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

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

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


  • 答案

    #include
    using namespace std;
    int sol_sup[100005];
    bool vis[100005];
    int n;
    int ans;
    
    bool check(int idx)
    {
    	if (vis[sol_sup[idx]]) return false;//上级在队伍中,不行
    	return true;
    }
    
    void choose(int sum, int need, int idx)
    {
    	//选到了需要的成员数
    	if (sum == need)
    	{
    		ans++;
    		return;
    	}
    	//要求从已有的成员中的最后一个编号开始再选,防止出现选择了例如123和312的情况
    	for (int i = idx + 1; i <= n; i++)
    	{
    		if (check(i))
    		{
    			vis[i] = 1;
    			choose(sum + 1, need, i);
    			vis[i] = 0;
    		}
    	}
    }
    
    int main()
    {
    	//输入
    	cin >> n;
    	sol_sup[1] = 1;
    	for (int i = 2; i <= n; i++) cin >> sol_sup[i];
    
    	//选1~n个成员
    	for (int i = 1; i <= n; i++)
    	{
    		memset(vis, 0, sizeof(vis));
    		choose(0, i, 0);
    	}
    
    	cout << ans;
    	return 0;
    }
    

你可能感兴趣的:(#,蓝桥杯,c++,算法,数据结构)