ASP.NET less overflow javascript pdf github vector dynamic casting model angular material vue状态管理 vue表单 管理后台框架 jq遍历 jq去除空格 float占几个字节 pcie高速固态硬盘 mysql获取当前时间戳 python加注释 python环境配置 python位运算 java在线学习 java编程入门 java基本数据结构 java系统时间 java判断文件是否存在 java集合图 java列表 vbs脚本 忧思华光玉攻略 骁龙660和625 html特殊字符 java核心技术 js保留两位小数 tt语音官网 视频解析软件 密码翻译 ip地址切换器 jsp源代码
当前位置: 首页 > 学习教程  > 编程语言

第五届蓝桥杯省赛A组c/c++

2020/10/8 19:34:20 文章标签:

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

第一题
一个串的子串是指该串的一个连续的局部。如果不要求连续,则可称为它的子序列。
比如对串: “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;
}

答案 : f(x, y + 1), f(x + 1, y)

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

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

如图:

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

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

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

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

答案:3.13

第三题
如果x的x次幂结果为10,你能计算出x的近似值吗?显然,这个值是介于2和3之间的一个数字。请把x的值计算到小数后6位(四舍五入),并填写这个小数值。

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

#include <iostream>
#include <cstdio>
#include <cmath>

using namespace std;

int main()
{
	double x = 2;
	for(;x <= 3.0;x += 0.00000001)
	{
		if(fabs(pow(x,x) - 10) < 0.000001)
			printf("%.6lf\n",x); 
	}
	return 0;
}

浮点数二分:

#include <iostream>
#include <cstdio>
#include <cmath>
#define eps 1e-7

using namespace std;

double f(double x)
{
	return pow(x, x);
}

int main()
{
	double l = 2.0, r = 3.0, mid;
	for (int i = 1; i <= 100; i++)
	{
		mid = (l + r) / 2.0;
		if (f(mid) - 10 > eps) r = mid;
		else l = mid;
	}
	printf("%.6f", mid);
	return 0;
}

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

17126425374635

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

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

注意:只填写这个14位的整数,不能填写任何多余的内容,比如说明注释等。
思路分析:
1.这些数放到哪个位置上
2.这个位置可以放哪个数

枚举位置

#include<iostream>
#include<string>
using namespace std;
int num[15] = {0,7,4,0,0,0,0,4,0,7,0,0,0,0,0};
int v[8] = {0};
void dfs(int pos)
{
	if(num[pos]) dfs(pos + 1);//如果已经放,当前位置加一 
	if(pos == 15)//枚举结束 
	{
		for(int i = 1;i <= 14;i++)
		cout << num[i] << " ";
		return;
	}
	for(int i = 1;i <= 7;i++)//在未放数的位置尝试放1-7的数 
	{
		if(v[i]) continue;//该数已用过 
		int back = i + pos + 1;//对称的位置 
		if(pos > 14) continue;//不符合条件 
		if(num[pos] == 0 && num[back] == 0)
		{
			num[pos] = num[back] = i;//放数 
			v[i] = 1;
			dfs(pos + 1);
			v[i] = 0;//回溯 
			num[pos] = num[back] = 0;
		} 
	}
}
int main()
{
	v[4] = v[7] = 1;
	dfs(1);//对十四个位置进行枚举 
	return 0;
}

按照n=1~7进行DFS:我们每次尝试在当前存在的若干空位中放入n,如果可以放入,就往下搜索n+1;

#include<bits/stdc++.h>
using namespace std;
int num[15]={0,7,4,0,0,0,0,4,0,7,0,0,0,0,0};
void dfs(int n)
{
    if(n==4) dfs(n+1);//4已经用过 
    if(n==7)
    {
        for(int i=1;i<=14;i++) printf("%d",num[i]); printf("\n");
        return;
    }

    for(int i=1;i<=14;i++)
    {
        if(i==1 || i==2 || i==7 || i==9) continue;
        int bak=i+n+1;
        if(bak>14) continue;

        if(num[i]==0 && num[bak]==0)
        {
            num[i]=num[bak]=n;
            dfs(n+1);
            num[i]=num[bak]=0;
        }
    }
}
int main()
{
    dfs(1);
    return 0;
} 

第五题
勾股定理,西方称为毕达哥拉斯定理,它所对应的三角形现在称为:直角三角形。已知直角三角形的斜边是某个整数,并且要求另外两条边也必须是整数。求满足这个条件的不同直角三角形的个数。

【数据格式】

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

例如,输入:

5
程序应该输出:

1
再例如,输入:

100
程序应该输出:

2
再例如,输入:

3
程序应该输出:

0

#include<iostream>
#include<string>
using namespace std;
int n,res;
int main()
{
	cin >> n;
	for(int a = 1; a <= n;a++)
	{
		for(int b = 1;b <= n;b++)
		{
			if(a + b >= n && a * a + b * b == n * n)//注意两边大于等于第三边
			{
				cout << a << "  " << b << " " << n << endl;
				res++;
			}
		}
	}
	cout << res / 2;
	return 0;
}

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

思路:暴力枚举,尝试把1-9数放入每个坐标,检查大方格和小方格合法性

#include<iostream>
#include<cstdio>
using namespace std;
const int n = 9;
char g[n][n];//图 
bool check(int x,int y,char ch)//检查是否合法 
{
	for(int i = 0;i < 9;i++)//大方格当前行和列是否合法 
	{
		if(g[x][i] == ch || g[i][y] == ch)//该数已经出现过 
		 	return false; 	
	}
	int a = x / 3 * 3, b = y / 3 * 3;//转化成该带你所在的小方格起始地址 
	for (int i = a; i <= a + 2; i++)
	for (int j = b; j <= b + 2; j++)
	{
		if(g[i][j] == ch)//该数已经出现过
		return false;	
	}	
	return true;
}

void dfs(int x,int y)//依次对每个位置进行枚举 
{
	if(y == n)//列走到尽头 
	{
		x ++;
		y = 0;
	}
	if(x == n)//枚举结束 
	{
		for(int i = 0;i < n;i++)
		{
			for(int j = 0;j < n;j++)
			cout << g[i][j];
			cout << endl; 
		}
		exit(0);
	}
	if(g[x][y] - '0') dfs(x,y + 1);//该数已经枚举过 
	else
	{
		for(int i = 1;i <= 9;i++)//尝试把1-9放入 
		{
			if(check(x,y,i + '0'))//检查合法性 
			{
				g[x][y] = i + '0';
				dfs(x,y + 1);
				g[x][y] = '0';	//回溯恢复现场 
			}
		}	
	}
	
}
int main()
{
	for(int i = 0;i < n;i++)
	for(int j = 0;j < n;j++)
	cin >> g[i][j];
	dfs(0,0);
	return 0;
}

第七题
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

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

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

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

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

分析
这题是经典的树形DP问题,对于第 i 个士兵,它可以去也可以不去。我们定义:

f[i][1]:表示i士兵去;f[i][0]:表示i士兵不去。

那么状态转移就很简单了。如果i士兵不去,那么其直接下属可以去也可以不去;如果i士兵去,那么其直接下属一定不能去。即:
f[i][0]=f[i][0]×∏(f[son][1]+f[son][0])
f[i][1]=f[i][1]×∏f[son][0]
注意:这里还需要排除G将军和士兵都不去的非法情况。

代码

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int N = 100010, mod = 10007;

int n;
int f[N][2];
int h[N], e[N], ne[N], idx;

void add(int a, int b)
{
	e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

void dfs(int u)
{
	f[u][0] = f[u][1] = 1;
	for (int i = h[u]; ~i; i = ne[i])
	{
		int j = e[i];
		dfs(j);
		f[u][0] = (f[u][0] * (f[j][0] + f[j][1])) % mod;
		f[u][1] = f[u][1] * f[j][0] % mod;
	}
}

int main()
{
	cin >> n;
	memset(h, -1, sizeof h);
	for (int i = 2; i <= n; i++) 
	{
		int father;
		cin >> father;
		add(father, i);
	}
	dfs(1);
	cout << (f[1][0] + f[1][1] - 1) % mod << endl;
	return 0;
}

本文链接: http://www.dtmao.cc/news_show_250158.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?