2017第八届蓝桥杯国赛c++B组

2017第八届蓝桥杯国赛c++B组

36进制

对于16进制,我们使用字母A-F来表示10及以上的数字。
如法炮制,一直用到字母Z,就可以表示36进制。
36进制中,A表示10,Z表示35,AA表示370
你能算出 MANY 表示的数字用10进制表示是多少吗?
请提交一个整数,不要填写任何多余的内容(比如,说明文字)

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int main(){
	string s;
	cin >> s;
	int len = s.length();
	LL res = 0;
	for(int i = 0; i < len ; i++)
	{
		res = res * 36 + s[i] - 'A' + 10;
	}
	cout << res ;
	return 0;
}

瓷砖样式

小明家的一面装饰墙原来是 310 的小方格。
现在手头有一批刚好能盖住2个小方格的长方形瓷砖。
瓷砖只有两种颜色:黄色和橙色。
小明想知道,对于这么简陋的原料,可以贴出多少种不同的花样来。
小明有个小小的强迫症:忍受不了任何2
2的小格子是同一种颜色。
(瓷砖不能切割,不能重叠,也不能只铺一部分。另外,只考虑组合图案,请忽略瓷砖的拼缝)
显然,对于 23 个小格子来说,口算都可以知道:一共10种贴法,如下图所示
但对于 3
10 的格子呢?肯定是个不小的数目,请你利用计算机的威力算出该数字。
注意:你需要提交的是一个整数,不要填写任何多余的内容(比如:说明性文字)

在这里插入图片描述
参考文章

#include<bits/stdc++.h>
using namespace std;
int g[20][20];
set<string> st;
int n ,m;
bool judge(){//检查 2x2 的格子中是否颜色相同
	for(int i = 1; i < n; i++){
		for(int j = 1; j < m; j++){//判断是否在图中 1+1+1+1 0+0+0+0
			if((g[i][j] + g[i][j + 1] + g[i + 1][j] + g[i + 1][j + 1]) % 4 == 0)
				return false;
		}
	}
	return true;
}
void dfs(int x,int y){
	if(x == n + 1){//如果已经超出了最后一行 
		if(judge()){
			string ans = "";
			for(int i = 1; i <= n; i++){
				for(int j = 1; j <= m; j++){
					char str[5];
					sprintf(str,"%d",g[i][j]);
					ans += str;//记录下各个状态 
				}
			}
			st.insert(ans);//利用set去重,求不同的方案个数 
		}
		return ;
	}
	if(g[x][y] == -1){//如果当前格子没有涂颜色 
		if(y + 1 <= m && g[x][y + 1] == -1){//可以横着 
			for(int i = 0; i < 2; i++){//依次给这个格子图上0,1两种状态的颜色 
				g[x][y] = g[x][y + 1] = i;
				if(y + 2 <= m) dfs(x, y + 2); 
				else dfs(x + 1, 1);
				g[x][y] = g[x][y + 1] = -1; //恢复现场 
			}
		}
		if(x + 1 <= n && g[x + 1][y] == -1){//可以竖着 
			for(int i = 0; i < 2; i++){//依次给这个格子图上0,1两种状态的颜色 
				g[x][y] = g[x + 1][y] = i;
				if(y + 1 <= m) dfs(x, y + 1);
				else dfs(x + 1, 1);
				g[x][y] = g[x + 1][y] = -1;//恢复现场 
			}
		}
	}else{//如果当前格子已经有颜色了,那么就根据条件进入右边或者下面的格子 
		if(y == m) dfs(x + 1, 1);//这里表示当前这一行已经满了,下一个从下一行的第一个开始 
		else dfs(x ,y + 1);//这一行没满就下一列 
	}
}
int main(){
	cin >> n >> m;
	memset(g,-1,sizeof g);
	dfs(1,1);
	cout << st.size();
	return 0;
}

发现环

小明的实验室有N台电脑,编号1~N。原本这N台电脑之间有N-1条数据链接相连,恰好构成一个树形网络。在树形网络上,任意两台电脑之间有唯一的路径相连。
不过在最近一次维护网络时,管理员误操作使得某两台电脑之间增加了一条数据链接,于是网络中出现了环路。环路上的电脑由于两两之间不再是只有一条路径,使得这些电脑上的数据传输出现了BUG。
为了恢复正常传输。小明需要找到所有在环路上的电脑,你能帮助他吗?
输入
第一行包含一个整数N。
以下N行每行两个整数a和b,表示a和b之间有一条数据链接相连。
对于30%的数据,1 <= N <= 1000
对于100%的数据, 1 <= N <= 100000, 1 <= a, b <= N
输入保证合法。
输出
按从小到大的顺序输出在环路上的电脑的编号,中间由一个空格分隔。
样例输入:
5
1 2
3 1
2 4
2 5
5 3
样例输出:
1 2 3 5

参考文章

#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int N = 1e5 + 5;
int n;
vector<int> mp[N];
queue<int > q;
int degree[N],vis[N];
void fun(){
	for(int i = 1; i <= n; i++){
		if(degree[i] == 1){
			q.push(i);
			vis[i] = 1;//将度为1,即非环中的点进行标记 
		}
	}
	while(!q.empty()){
		int front = q.front();
		q.pop();
		for(int i = 0; i < mp[front].size(); i++){
			int tp = mp[front][i];
			degree[tp] --;
			if(degree[tp] == 1){
			//环的性质,当去除掉非环中的点 ,环中的度依旧大于1 
				q.push(tp);
				vis[tp] = 1;
			}
		}
	}
}
int main(){
	scanf("%d",&n);
	for(int i = 0; i < n; i++){\
		int a,b;
		scanf("%d %d",&a,&b);
		mp[a].push_back(b);
		mp[b].push_back(a);
		degree[a]++;
		degree[b]++;
	}
	fun();
	bool flag = true;
	for(int i = 1; i <= n; i++){
		if(!vis[i]){
			if(flag){
				printf("%d",i);
				flag = false;
			}
			else
				printf(" %d",i);
		}
	}
	return 0;
}

对局匹配

小明喜欢在一个围棋网站上找别人在线对弈。这个网站上所有注册用户都有一个积分,代表他的围棋水平。
小明发现网站的自动对局系统在匹配对手时,只会将积分差恰好是K的两名用户匹配在一起。如果两人分差小于或大于K,系统都不会将他们匹配。
现在小明知道这个网站总共有N名用户,以及他们的积分分别是A1, A2, … AN。
小明想了解最多可能有多少名用户同时在线寻找对手,但是系统却一场对局都匹配不起来(任意两名用户积分差不等于K)?
输入
第一行包含两个个整数N和K。
第二行包含N个整数A1, A2, … AN。
对于30%的数据,1 <= N <= 10
对于100%的数据,1 <= N <= 100000, 0 <= Ai <= 100000, 0 <= K <= 100000
输出
一个整数,代表答案。
样例输入:
10 0
1 4 2 8 5 7 1 4 2 8
样例输出:
6
再比如,
样例输入:
10 1
2 1 1 1 1 4 4 3 4 4
样例输出:
8

dp就是靠感觉的,正确的感觉在这里
参考文章1
参考文章2

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 100001;
int cnt[N];
int dp[N];
int arr[N]; 
int main(){
	int n,k;
	cin >> n >> k;
	for(int i = 0; i < n; i++){
		int x;
		cin >> x;
		cnt[x]++;
	}
	int ans = 0;
	if(k == 0){
		for(int i = 0; i < N; i++){
			if(cnt[i])
				ans ++;
		}
		cout << ans;
	}
	else{
		for(int i = 0; i < k; i++){
			int index = 0;
			for(int j = i; j < N ; j += k){
				arr[index++] = cnt[j];
			}
			dp[0] = arr[0];
			for(int j = 1; j < index; j++){
				if(j == 1)
					dp[j] = max(dp[0], arr[1]);
				else
					dp[j] = max(dp[j - 2] + arr[j], dp[j - 1]);
			}
			ans += dp[index - 1];//前面index多加了依次,所以取index-1的dp值 
		}
		cout << ans;
	}
	return 0;
}

观光铁路

跳蚤国正在大力发展旅游业,每个城市都被打造成了旅游景点。
许多跳蚤想去其他城市旅游,但是由于跳得比较慢,它们的愿望难以实现。这时,小C听说有一种叫做火车的交通工具,在铁路上跑得很快,便抓住了商机,创立了一家铁路公司,向跳蚤国王请示在每两个城市之间都修建铁路。
然而,由于小C不会扳道岔,火车到一个城市以后只能保证不原路返回,而会随机等概率地驶向与这个城市有铁路连接的另外一个城市。
跳蚤国王向广大居民征求意见,结果跳蚤们不太满意,因为这样修建铁路以后有可能只游览了3个城市(含出发的城市)以后就回来了,它们希望能多游览几个城市。于是跳蚤国王要求小C提供一个方案,使得每只跳蚤坐上火车后能多游览几个城市才回来。
小C提供了一种方案给跳蚤国王。跳蚤国王想知道这个方案中每个城市的居民旅游的期望时间(设火车经过每段铁路的时间都为1),请你来帮跳蚤国王。
【输入格式】
输入的第一行包含两个正整数n、m,其中n表示城市的数量,m表示方案中的铁路条数。
接下来m行,每行包含两个正整数u、v,表示方案中城市u和城市v之间有一条铁路。
保证方案中无重边无自环,每两个城市之间都能经过铁路直接或间接到达,且火车由任意一条铁路到任意一个城市以后一定有路可走。
【输出格式】
输出n行,第i行包含一个实数ti,表示方案中城市i的居民旅游的期望时间。你应当输出足够多的小数位数,以保证输出的值和真实值之间的绝对或相对误差不超过1e-9。
【样例输入】
4 5
1 2
2 3
3 4
4 1
1 3
【样例输出】
3.333333333333
5.000000000000
3.333333333333
5.000000000000
【样例输入】
10 15
1 2
1 9
1 5
2 3
2 7
3 4
3 10
4 5
4 8
5 6
6 7
6 10
7 8
8 9
9 10
【样例输出】
10.000000000000
10.000000000000
10.000000000000
10.000000000000
10.000000000000
10.000000000000
10.000000000000
10.000000000000
10.000000000000
10.000000000000
【数据规模与约定】
对于10%的测试点,n <= 10;
对于20%的测试点,n <= 12;
对于50%的测试点,n <= 16;
对于70%的测试点,n <= 19;
对于100%的测试点,4 <= k <= n <= 21,1 <= u, v <= n。数据有梯度。

参考文章
有难度,这个题还没有正解,下面代码只能过部分样例

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int n, m, a, b, sum ,d[100]; 
int main(){
	cin >> n >> m;
	while(m--) cin >> a >> b,d[a] ++, d[b]++;
	for(int i = 1; i <= n; i++) sum += d[i];
	for(int i = 1; i <= n; i++) printf("%.12lf\n", 1.0 * sum / d[i]);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值