赞
踩
昨天下午参加了蓝桥杯校内选拔赛。
不谈别人,只谈自己,我觉得这次校赛的发挥还算正常,大概做出了5/8或4/5吧,剩下几道题没时间看了。
应该提高做题效率了…
Excel单元格的地址表示很有趣,它使用字母来表示列号。
比如,
A表示第1列,
B表示第2列,
Z表示第26列,
AA表示第27列,
AB表示第28列,
BA表示第53列,
…
当然Excel的最大列号是有限度的,所以转换起来不难。
如果我们想把这种表示法一般化,可以把很大的数字转换为很长的字母序列呢?
本题目既是要求对输入的数字, 输出其对应的Excel地址表示方式。
样例输入:
26
样例输出:
Z
样例输入:
2054
样例输出:
BZZ
我们约定,输入的整数范围[1,2147483647]
【分析】
这道题最简单,却花了我最多的时间(大概半个小时),原因是自己没有进行预热,导致很晚才进入状态。
这道题的本质就是类似于将10进制转化为26进制,只不过用A到Z表示1到26。
【我的代码】
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int maxn = 100 + 10; int main() { int n; while (cin >> n) { int a[maxn], cnt = 0; while (n) { int t = (n - 1) % 26 + 1;//这样写不存在0的情况 a[cnt++] = t; n = (n - t) / 26; //去余降幂 } for (int i = cnt - 1;i >= 0;i--) cout << (char)(a[i] + 'A' - 1); cout << endl; } return 0; }
【问题描述】
如果用a b c d这4个字母组成一个串,有4!=24种,如果把它们排个序,每个串都对应一个序号:
abcd 0
abdc 1
acbd 2
acdb 3
adbc 4
adcb 5
bacd 6
badc 7
bcad 8
bcda 9
bdac 10
bdca 11
cabd 12
cadb 13
cbad 14
cbda 15
cdab 16
cdba 17
…
现在有不多于10个两两不同的小写字母,给出它们组成的串,你能求出该串在所有排列中的序号吗?
【输入格式】
一行,一个串。
【分析】
考试时候以为自己写错了,结果仔细读题发现没写错…
全都用生成排列,算是对最近一阵学习的算法的练习了吧(笑哭)
【代码】
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 10000 + 10; int main() { int pos = 0; char str[maxn], cpy[maxn]; cin >> str; int len = strlen(str); strcpy(cpy, str); sort(str, str + len); do { if (!strcmp(cpy, str)) { cout << pos << endl; break; } pos++; } while (next_permutation(str, str + len)); return 0; }
串可以按照字典序进行比较。例如:
abcd 小于 abdc
如果给定一个串,打乱组成它的字母,重新排列,可以得到许多不同的串,在这些不同的串中,有一个串刚好给定的串稍微大一些。科学地说:它是大于已知串的所有串中最小的串。你的任务就是求出这个“稍大的串”。
样例输入:
输入串:
abfxy
样例输出:
abfyx
样例输入:
输入串:
ayyyxxff
样例输出:
fafxxyyy
数据规模约定:
输入的串不超过1000个字符。
特例:
如果已知的串已经是所有重组串中最大的,则原样输出读入的那个串
【分析】
水题,使用dfs生成1–n的全排列,或者直接使用C++STL里的next_permutation(a,a+n)即可。
考试的时候太心急了没有看到特例,哭辽…
【代码】
1.dfs实现
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn = 10000 + 10; char str[maxn], mark[maxn], Min[maxn]; int vis[maxn], len = 0; void dfs(int cur) //从0开始往里填数, 到cur==len为止 { if (cur == len) { if (strcmp(mark, str) == 1)//如果生成序列比原始序列大 { if (strcmp(mark, Min) == -1) strcpy(Min, mark); } return; } if (cur >= len) return; for (int i = 0;i < len;i++) { if (!vis[i]) { vis[i] = 1; mark[cur] = str[i]; dfs(cur + 1); mark[cur] = '\0'; vis[i] = 0; } } } int main() { cin >> str; len = strlen(str); int flag = 1; for(int i=0;i<len-1;i++) if (str[i] < str[i + 1]) { flag = 0; break; } if (flag) { cout << str << endl; return 0; } for (int i = 0;i < maxn;i++) Min[i] = 'z'; memset(vis, 0, sizeof(vis)); dfs(0); cout << Min << endl; //system("pause"); return 0; }
2.STL里的next_permutation(a,a+n)
#include<iostream> #include<cstring> #include<algorithm> using namespace std; const int maxn = 10000 + 10; int main() { char str[maxn], cpy[maxn]; cin >> str; int flag = 1; for(int i=0;i<len-1;i++) if (str[i] < str[i + 1]) { flag = 0; break; } if (flag) { cout << str << endl; return 0; } int len = strlen(str); strcpy(cpy, str); sort(str, str + len); do { if (strcmp(str, cpy) == 1) { cout << str << endl; break; } } while (next_permutation(str, str + len)); return 0; }
【描述】
一般我们在对字符串排序时,都会按照字典序排序。当字符串只包含小写字母时,相当于按字母表"abcdefghijklmnopqrstuvwxyz"的顺序排序。
现在我们打乱字母表的顺序,得到一个26个字母的新顺序。例如"bdceafghijklmnopqrstuvwxyz"代表’b’排在’d’前,'d’在’c’前,'c’在’e’前……
给定N个字符串,请你按照新的字母顺序对它们排序。
输入:
第一行包含一个整数N。(1 <= N <= 1000)
第二行包含26个字母,代表新的顺序。
以下N行每行一个字符串S。 (|S| <= 100)
输出:
按新的顺序输出N个字符串,每个字符串一行。
样例输出:
5
bdceafghijklmnopqrstuvwxyz
abcde
adc
cda
cad
ddc
样例输出:
ddc
cda
cad
abcde
adc
【分析】
重新生成字典序,并依据新的字典序排序。
将新字典序的每个字符映射成对应位置的ID即可,使用map会很方便。
【代码】
#include<iostream> #include<cstdio> #include<map> #include<string> #include<cstring> #include<algorithm> using namespace std; const int maxn = 10000 + 10; map<char, int>mm; int judge_lower(string str1,string str2) { int flag = 1; int len1 = str1.length(); int len2 = str2.length(); int max_len = len1 > len2 ? len1 : len2; for (int i = 0;i < max_len;i++) { char ch1 = str1[i], ch2 = str2[i]; if (mm[ch1] == mm[ch2]) continue; else { flag = mm[ch1] < mm[ch2] ? 1 : 0; break; } } if (flag) return 1; return 0; } int main() { char buf[27]; string str[maxn]; int n; cin >> n; getchar(); cin >> buf; for (int i = 0;i < 26;i++) //为每个字母重新生成字典序 mm[buf[i]] = i; for (int i = 0;i < n;i++) cin >> str[i]; for (int i = 0;i < n;i++) { for (int j = 0;j < n - i - 1;j++) { if (judge_lower(str[j + 1], str[j])) { string temp; temp = str[j];str[j] = str[j + 1];str[j + 1] = temp; } } } for (int i = 0;i < n;i++) cout << str[i] << endl; return 0; }
【描述】
如果一个1~N的排列P=[P1, P2, … PN]中的任意元素Pi都满足|Pi-i| ≤ 1,我们就称P是1-偏差排列。
给定一个N,请你计算一共有少个不同的排列是1-偏差排列。
例如对于N=3,有3个1-偏差排列:[1, 2, 3], [1, 3, 2], [2, 1, 3]。
输入
一个整数N。
对于50%的数据,1 ≤ N ≤ 15
对于100%的数据,1 ≤ N ≤ 50
输出
一个整数表示答案
样例输入
3
样例输出
3
【分析】
最初使用dfs生成排列,发现搜索超过十层的时候就很难再进行了,观察结果发现是类似于斐波那契数列…
为了提供一种思路,先放出用深搜写的代码…
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; const int maxn = 10000 + 10; int a[maxn]; int vis[maxn], n = 0; long long cnt = 0; bool judge() { for (int i = 1;i <= n;i++) if (abs(a[i] - i) > 1) return false; return true; } void dfs(int cur) //从0开始往里填数, 到cur==len为止 { if (cur == n + 1) { if (judge()) cnt++; return; } if (cur >= n + 1) return; for (int i = 1;i <= n;i++) { if (!vis[i]) { vis[i] = 1; a[cur] = i; dfs(cur + 1); vis[i] = 0; a[cur] = 0; } } } int main() { cin >> n; dfs(1); cout << cnt << endl; system("pause"); return 0; }
简化版:
#include<iostream>
using namespace std;
const int maxn = 50 + 10;
int main()
{
int n;
long long a[maxn];
a[1] = 1;a[2] = 2;a[3] = 3;
for (int i = 4;i <= 50;i++)
a[i] = a[i - 1] + a[i - 2];
while (cin >> n)
cout << a[n] << endl;
return 0;
}
H国的国王有很多王子,这些王子各自也都有很多王孙,王孙又各自有很多后代…… 总之,H国王族的族谱形成了一棵以国王为根的树形结构。
根据H国的法律,王族的继承顺位这样规定的:
假设A和B是两位王族
1 如果其中一位是另一位的直系父亲、祖先,则辈份高的王族继承顺位更高
2 否则,假设C是A和B的最近公共祖先。显然A和B一定是C的两位不同子嗣的后代。其中C较年长的子嗣的后代的继承顺位更高
按时间顺序给出所有国王后代的出生和死亡记录,请你计算所有还活着的后代的继承顺位。
输入
第一行包含一个整数N和一个只包含大写字母和数字的字符串,分别代表记录的条数和国王的名字。
以下N行每行包含一条记录:
birth name1 name2 代表name1的儿子name2出生
death name 代表name死亡
1 <= N <= 10000
名字长度不超过20,并且没有重名的王族。
输出
按继承顺位从高到低输出每位王族的名字。(不包括国王)
每个名字一行。
样例输入
4 KING
birth KING ALI
birth KING BOB
birth ALI CARRO
death ALI
样例输出
CARRO
BOB
小Hi开发了一个在线玩斗地主的游戏平台。现在平台上有N名用户正在寻找对局,其中第i名用户的积分是Ai。
小Hi希望自己的平台可以自动将这N名用户匹配成尽量多的3人牌局。同时他希望一局中的3名用户两两之间的积分差不超过K。
你能帮小Hi实现这个自动对局匹配的算法吗?
假设现在正有7人在寻找对局,积分分别是[30, 31, 30, 34, 33, 32, 34]并且K = 1,这时最多可以匹配出2局:[30, 31, 30]和[34, 33, 34]。
输入
第一行包含两个整数,N和K。 (1 ≤ N ≤ 100000, 1 ≤ K ≤ 100000)
第二行包含N整数Ai。(0 ≤ Ai ≤ 100000)
输出
一个整数表示最多能匹配出的对局数量。
样例输入
7 2
30 31 30 34 33 32 34
样例输出
2
描述
小Hi的面前摆放了N张卡片,每张卡片都有A和B两面。其中第i张卡片的A面写着一个整数Ai,B面写着一个整数Bi。
一开始所有卡片都是A面向上。现在小Hi必须选择一张卡片,将其翻成B面向上。
设N张卡片向上那一面的数字组成的集合是S,那么游戏的得分是:最小的不属于S的正整数。
例如S={1, 2, 4, 6, 7},则得分是3。
你能算出小Hi最多能得多少分么?
输入
第一行包含一个整数N。
第二行包含N个整数Ai。
第三行包含N个整数Bi。
对于50%的数据,1 ≤ N ≤ 1000
对于100%的数据,1 ≤ N ≤ 100000 1 ≤ Ai, Bi ≤ 1000000
输出
输出最大得分
样例输入
5
1 2 3 5 6
3 4 3 4 4
样例输出
6
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。