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