这场比赛开打第二题就理解错意思了,还以为只能用3个消除和5个消除其中一种呢,结果就是死活a不过去,第三题根本读不懂题意,这蓝桥杯的题面我只能说出的是一言难尽啊。。第四题写出来一点但是后来知道是错了,不会正解,补的,第五题根本没思路,也是补的思路。
消灭卡片https://www.lanqiao.cn/problems/20035/learning/?contest_id=222标签:暴力
这道题的意思是用最少次数来解决全部卡片,有一次消灭三个,和一个消灭5个两种方法,但是无论选择哪种方法,一定要保证最后没有剩余,也就是消灭必须是一次性的是正好消灭的,不能最后剩4个,然后选择用一次5个消灭的方法,这是不允许的。
思考思路就是尽可能选择用一次消灭5个的,这样使得最后次数最少,如果能整除就没有然后了,如果是余1,那就少用一次5连,变成剩六个然后两次三连,如果余2,就是少用两次五连,然后连着4个三连,以此类推,可以发现只要总数n是够的,总是可以被消灭的,不能被消灭的情况只会发生在n不够的情况里,详见代码。
#include <iostream>
using namespace std;
int t, n;
int main()
{
cin >> t;
while (t -- )
{
cin >> n;
if (n < 5)
{
if (n % 3 == 0 ) cout << 1 << endl;
else cout << -1 << endl;
continue;
}
if (n % 5 == 0 ) cout << n / 5 << endl;
else if (n % 5 == 1 && n >= 6 ) cout << n / 5 - 1 + 2 << endl;
else if (n % 5 == 2 && n >= 12) cout << n / 5 - 2 + 4 << endl;
else if (n % 5 == 3) cout << n / 5 + 1 << endl;
else if (n % 5 == 4 && n >= 9) cout << n / 5 - 1 + 3 << endl;
else cout << -1 << endl;
}
return 0;
}
3.招募队员【算法赛】 - 蓝桥云课https://www.lanqiao.cn/problems/20036/learning/?contest_id=222标签:前缀标记、数组
第三题招募队员,题面说的是需要选择连续区间【l,r】我以为的是一队五个人中选择【l,
r】区间,然后剩下的行也是这样选择,看最后能得到最多几个队员,但是与样例对不上。。就比如说选择2-4区间,然后第二行也这么选,看结果。后来看题解才发现是选择连续【l,r】是跨行的,不能间断的选择区间,然后该区间每一行都出现过1-5中任意数字的情况,比如说第一行出现过1,第二行也出现过,那么就连起来了,但是第三行没有出现,那么就是最多能选两个。是这样的,而且1-5的数字区间互不影响,并不是说前两行为了1而选择的区间,那么2也一定要选择该区间,每个数字都可以选择任意的连续的包含该数字的区间,求最多能选多少人,注意只有连续区间才能选人累加,不是连续区间要重新计算选人最大值。
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int a[N][6], n;
int main()
{
cin >> n;
for (int i = 1; i <= n; ++ i )
for (int j = 1; j <= 5; ++ j )
{
int x; cin >> x;
a[i][x] = 1;
}
for (int k = 1; k <= 5; ++ k )
{
int sum = 0, t = 0;
for (int i = 1; i <= n; ++ i )
{
if (a[i][k] == 1 ) t ++;
else t = 0;
sum = max(sum, t);
}
cout << sum << ' ';
}
return 0;
}
这里给出的做法是,每一行在读入数字时候,就做上标记,标记是来标明该行是否存在1-5的数字,然后依次计算1-5按顺序计算,看每一行是否有这个数字的标记,然后有就累加,否则清空,最后取最大值输出即可。
4.能量晶石【算法赛】 - 蓝桥云课https://www.lanqiao.cn/problems/20029/learning/?contest_id=222标签:思维、数学
题面含义要求找到最小去能量矿脉的次数,由于dp不熟,比赛时候我选择使用二分法来做,然后排序后判断,相邻数字插值,将这个累加在变量t上,之后的每一次相邻都累加t比较,看最后累加多少t,然后再和二分答案比较,后来模拟一下发现是错误的,有很多时候虽然只有一个数字和其他数字差1,其他数字都相等,但是仍然需要进行多次累加,我就想着模拟找规律,以为是规律题,但是也没做出来。
正解思维是正向求解十分困难,要逆着想,一般情况我们模拟肯定就是让最大的那个人出去采矿,然后把矿分给其他人,让其他人加1,逆着想就是其他人加1,相当于我减1,假设你是最大的和其他人只差1,那么需要你去采矿分给别人,那我们主动丢出去一个,不就能达到相等了吗?依据这个思路,我们把出去给别人采矿让其他人全部+1的行为,变成自我放弃掉一些矿石,我们找到最少拥有矿石数目是多少,然后其他的人依次减掉这些累加一起,就是需要出去的次数,因为其他人都丢了结果就是全部数目相等,而其他人出去采矿,让别人增加矿石,最后要达到的目的也是为了让矿石数目相等,所以理论上来讲,答案是一致的。
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int a[N];
int main()
{
int n;
int mina = 1e9 + 10;
cin >> n;
for (int i = 0; i < n; ++ i )
{
int x; cin >> x;
a[i] = x;
mina = min(mina, x);
}
long long ans = 0;
for (int i = 0; i < n; ++ i ) ans += a[i] - mina;
cout << ans << endl;
return 0;
}
5.缺失的环节【算法赛】 - 蓝桥云课https://www.lanqiao.cn/problems/20031/learning/?contest_id=222标签:数学、思维
这道题容易re或mle之处在于枚举字符串时,枚举出的数字可能很大,大到数组装不进去这些数字,经过分析可知,字符串最长为1e5,且根据样例找规律,当长度为3时,可能的答案有0、1、2、3、4、5、6,也就是最多到n*(n+1)/ 2,数列是等差数列,根据等差数列公式就是那个式子了。所以最多长度为1e5的字符串,最大产生数字大概就是10^10/2,差不多是几个亿,而2的34次幂差不多就能涵盖所有情况,但是为了避免不必要的麻烦我们多判一段,当子串枚举没超过40我们都存到容器里,记得要开longlong,先预处理完字串构成的数字后,从最小值0开始看容器是否能找到,这里容器我们用的set,不用数组因为数组遍历是on的,容器set的count是ologn的。
#include <iostream>
#include <set>
using namespace std;
string s;
int n;
typedef long long ll;
int main()
{
cin >> n >> s;
set<ll> num;
for (int i = 0; i < n; ++ i )
{
ll t = 0;
for (int j = i; j < n; ++ j )
{
if (j - i > 40) break;
t = t * 2 + (s[j] - '0');
num.insert(t);
}
}
int ans = 0;
while (num.count(ans)) ans ++;
cout << ans << endl;
return 0;
}
以上便是全部内容,补完来看其实没那么难,但是很多东西就是自己想不到,或许多刷一点就可以了吧。。。
制作不易,有帮助的话,请三连支持蟹蟹