评价:一般~~(超级棒)~~
模拟赛
1. 2023春季基础热身赛 第一场
排名第5,共600分,打了228分
速度慢了一点,没有做完题目,下次要快一点
2. 2023春季基础热身赛 第二场
排名第5,共600分,打了228分
算法的应用不够熟练,要多练习,熟能生巧
3.2023春季基础热身赛 第二场
排名第7,共600分,打了345分
对枚举等的优化不行,搜索题需要加强
4. 2023 年春季信息学普及 ~ 提高 挑战赛 - 中期测试
排名第48,共700分,打了100分
不能学以致用,要多实践
算法
1.分治
分治分治,就是“分而治之”,把一个复杂的问题拆分成两个及以上的问题,再把得到的子问题分解成更小的子问题…直到最后得到的子问题可以直接求解,这就是分治,也是许多高效算法的基础
例题:
南蛮图腾,快速幂
2. 前缀和
前缀和可以简单理解为【数列的前 n 项的和】
sum[0]=0;
sum[1]=sum[0]+a[1];
...
sum[i]=sum[i-1]+a[i];
3. 二分
二分查找(英语:binary search),也称折半搜索(英语:half-interval search)、对数搜索(英语:logarithmic search),是用来在一个有序数组中查找某一元素的算法。
拿1—100的猜数字举例,想一个数字,先从50对半猜,如果小于50就继续猜25,如果大于50就猜75,不停的对半猜,二分法也是一样,把问题不停的1分为2这就是二分
注意!!!:二分查找时,所以调用前必须保证元素有序。
二分的模板是:
while(l+1<r){
int mid=(l+r)/2;
if(check(mid)){
l=mid;
}
else {
r=mid;
}
二分答案
解题的时候往往会考虑枚举答案然后检验枚举的值是否正确。若满足单调性,则满足使用二分法的条件。把这里的枚举换成二分,就变成了「二分答案」
4.贪心
贪心算法(英语:greedy algorithm),是用计算机来模拟一个「贪心」的人做出决策的过程。这个人十分贪婪,每一步行动总是按某种指标选取最优的操作。而且他目光短浅,总是只看眼前,并不考虑以后可能造成的影响。
可想而知,并不是所有的时候贪心法都能获得最优解,所以一般使用贪心法的时候,都要确保自己能证明其正确性。
例题:
修改数组,凌乱的yyy / 线段覆盖
5.递推
递推算法是一种用若干步可重复运算来描述复杂问题的方法。递推是序列计算中的一种常用算法。通常是通过计算前面的一些项来得出序列中的指定项的值。
以斐波那契数列(1,1,2,3,5,8,13…)为例:
f[1] = 1;
f[2] = 1;
f[3] = f[1] + f[2];
f[4] = f[2] + f[3];
...
f[n] = f[n - 2] + f[n - 1];
6.LIS 和 LCS
LIS (Longest Increasing Subsequence的缩写)为最长上升子序列,例如1,2,3,4,5,6,那么最长的上升子序列就是6
LCS(Longest Common Subsequence的缩写),即最长公共子序列。一个序列,如果是两个或多个已知序列的子序列,且是所有子序列中最长的,则为最长公共子序列。LCS不是唯一的,它可以有很多种,例如 <A,B,C,B,D,A,B> 和 <B,D,C,A,B,A> 的最长子序列可以是 <B,C,A,B> 也可以是 <B,C,B,A> ,显然都成立
LIS模板:
#include <bits/stdc++.h>
using namespace std;
const int N = 105, inf = 1e9 + 10;
int a[N], f[N];
int n, ans = -inf;
int main() {
cin >> n;
for (int i = 1; i <= n; i ++) {cin >> a[i]; f[i] = 1;}
for (int i = 1; i <= n; i ++)
for (int j = 1; j < i; j ++)
if (a[i] > a[j]) f[i] = max(f[i], f[j] + 1);
for (int i = 1; i <= n; i ++)
ans = max(ans, f[i]);
cout << ans << '\n';
return 0;
}
LCS模板:
#include <bits/stdc++.h>
#define int long long
using namespace std;
char s1[2333], s2[2333];
int n, m;
int f[2333][2333];
signed main() {
scanf("%s", s1 + 1);
n = strlen(s1 + 1);
scanf("%s", s2 + 1);
m = strlen(s2 + 1);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (s1[i] == s2[j])
f[i][j] = f[i - 1][j - 1] + 1;
else
f[i][j] = max(f[i - 1][j], f[i][j - 1]);
}
}
cout << f[n][m];
return 0;
}