这里是paoxiaomo,一个现役ACMer,之后将会持续更新算法笔记系列以及笔试题题解系列
本文章面向想打ICPC/蓝桥杯/天梯赛等程序设计竞赛,以及各个大厂笔试的选手
感谢大家的订阅➕ 和 喜欢
本题总分:5分
【问题描述】 8100178706957568 这个数在用 x 进制表示时 (x ∈ [11,36]),仅包含数字而 不包含字母,请问x是多少。比如2588用16进制表示为a1c,包含字母a和 c。
【答案提交】 这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。暴力枚举11到36
【题目解析】
暴力枚举每个数字,一一检验,可得答案为32.
本题总分:5分 【问题描述】 有一个数组,包含1到n这n个整数,初始为一个从小到大的有序排列: {1, 2, 3, 4,··· ,n} 。一次随机交换操作指:均匀随机选取两个位置 i, j ∈ [1,n] 且 i \neqj ,然后交换数组中这两个位置上的数。那么对于n=51,对初始数组进行 两次随机交换操作之后,数组中的逆序对的数量的期望是多少个。 【答案提交】 这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个实数,在提交答案时只填写这个实数,四舍五入保留两位小数,填写多余的 内容将无法得分.
【题目解析】
暴力打表题,枚举每次交换的两个数字,然后检验即可,答案为65.33.
时间限制: 1.0s 内存限制: 256.0MB 本题总分:10分
【问题描述】 小蓝在环球旅行时来到了一座古代遗迹,里面并排放置了n个传送阵,进 入第i个传送阵会被传送到第ai 个传送阵前,并且可以随时选择退出或者继续 进入当前传送阵。 小蓝为了探寻传送阵中的宝物,需要选择一个传送阵进入,然后连续进入 之后的传送阵。小蓝希望尽可能多地进入传送门以便搜索宝物,同时他可以使 用一次魔法,从某个传送阵 j走到相邻的(第 j−1或第 j+1个)传送阵,请 问小蓝最多能到达多少个不同的传送阵?一个传送阵可多次进入,但在计算答 案时只算一个。
【输入格式】 输入的第一行包含一个正整数n。 第二行包含n个正整数a1,a2,··· ,an ,相邻整数之间使用一个空格分隔。
【输出格式】 输出一行包含一个整数表示答案。
【样例输入】
5
2 1 5 4 3
【样例输出】 4
【样例说明】 小蓝的路径可以是:1→2→3→5。其中2→3使用魔法。
【评测用例规模与约定】 对于20%的评测用例,1≤n≤1000; 对于所有评测用例,1≤n≤106,且a是1至n的一个排列。
【题目解析】
由a是1至n的一个排列这个条件得知,每个位置只有唯一的一个传送门能到达,由此推断,这个图是由一堆简单环组成,而每个环上各个点又是可以到达的,所以直接将环上点进行染色后枚举每两个相邻位置,如果两者颜色不同则可以相加并取最大值。
【参考代码】
void solve()
{
int n, tot = 0;
cin >> n;
vector a(n + 1), co(n + 1), siz(n + 1); // 输入数组,每个位置连通块的颜色,每种颜色的联通块大小
for (int i = 1; i <= n; i++)
cin >> a[i];
auto dfs = [&](int pos, auto dfs) -> void
{
co[pos] = tot;
siz[tot]++;
if (!co[a[pos]])
{
dfs(a[pos], dfs);
}
};
for (int i = 1; i <= n; i++)
{
if (!co[i])
++tot, dfs(i, dfs);
}
if (tot == 1)
{ // 特判所有的都在一个环上的情况
cout << n << endl;
}
int ans = 0;
for (int i = 1; i <= n; i++)
{
if (co[i] != co[i - 1])
{
ans = max(ans, siz[co[i]] + siz[co[i - 1]]); // 尽量取最大的两个相邻连通块
}
}
cout << ans << endl;
}
时间限制: 1.0s
内存限制: 256.0MB 本题总分:10分
【问题描述】 给定n 个由小写英文字母组成的字符串 s1,s2,··· ,sn ,定义前缀总分为 V = ∑
i 【输入格式】 输入的第一行包含一个正整数n。 接下来n行,每行包含一个字符串s_i。 【输出格式】 输出一行包含一个整数表示答案。 【样例输入】 3 aab bbb abb 【样例输出】 5 【样例说明】 将第二个字符串改为abb,得分为P(aab,abb)+P(aab,abb)+P(abb,abb) = 1 +1+3=5 【评测用例规模与约定】 对于20%的评测用例,1≤n≤20; 对于所有评测用例,1≤n≤200,1≤|si|≤200 ,其中 |si| 表示 si的长度。 【题目解析】 进行大量的字符串匹配问题,可以使用字典树来进行匹配,我们可以先建立字典树,然后枚举每个字符串上的每个字母并替换,对于每个被替换后的字符串一一跑一遍字典树即可,记得在统计前先将当前字符串的贡献删去。 【参考代码】 剩下的题目下次再更新。关注博主可以更快看到文章哦~int tr[4005][26], tot, num[4005];
string s[205];
void solve()
{
int n;
cin >> n;
int sum = 0, ans = 0; // 先统计所有的字符串如果不改变那么和是多少,用sum记录
for (int i = 1; i <= n; i++)
{
cin >> s[i];
int now = 0;
for (int j = 0; j < s[i].size(); j++)
{ // 经典字典树操作
if (!tr[now][s[i][j] - 'a'])
{
tr[now][s[i][j] - 'a'] = ++tot;
}
now = tr[now][s[i][j] - 'a'];
sum += num[now];
num[now]++;
}
}
ans = sum;
for (int i = 1; i <= n; i++)
{
int now = 0;
for (int j = 0; j < s[i].size(); j++)
{
if (!tr[now][s[i][j] - 'a'])
{
tr[now][s[i][j] - 'a'] = ++tot;
}
now = tr[now][s[i][j] - 'a'];
num[now]--;
sum -= num[now]; // 减去该串的贡献
}
for (int j = 0; j < s[i].size(); j++)
{
char fore = s[i][j]; // 记录原来的字符,方便改回去
for (int k = 0; k < 26; k++)
{
s[i][j] = 'a' + k;
now = 0;
int nu = 0;
for (int j = 0; j < s[i].size(); j++)
{
if (!tr[now][s[i][j] - 'a'])
{
break;
}
now = tr[now][s[i][j] - 'a'];
nu += num[now]; // 加上变换后该串的贡献
}
ans = max(ans, nu + sum);
}
s[i][j] = fore;
}
now = 0;
for (int j = 0; j < s[i].size(); j++)
{
if (!tr[now][s[i][j] - 'a'])
{
tr[now][s[i][j] - 'a'] = ++tot;
}
now = tr[now][s[i][j] - 'a'];
sum += num[now];
num[now]++; // 回退操作
}
}
cout << ans << endl;
}