比赛靠手机码代码真累QAQ
B-减成一
1)知识点
- 就是一道简单的动态规划。
2)看题目
- 就是你每次都可以让一个区间数字都-1,求最少几次全变1。
3)算法分析
- 一开始我以为不是连续区间,还直接就排个序来搞了。但是看到连续区间的时候我就发现这一定是个dp。
- 说到dp:动态规划最重要的就是递推和dp数组的含义。
- 首先我们讲一下dp数组的含义:这里重要的是数的位置。所以dp数组就是一个一维数组:dp[位置] = 最小次数。
- 然后是递推:
- 首先很简单,如果我们这一位比上一位要大,那么说明要比上一位要多操作x次(x为前后的差值)。
- 如果后面比前面小呢,就不用增加操作次数,因为可以在前面操作的时候就操作掉ta了。
- 就是这样,这是一道十分简单的动态规划。
4)算法操作
- 就先写一下dp数组的含义:
int dp[MAX];//dp[位置] = 最小次数
- 然后是我们的递推公式:
dp[0] = 0; info[0] = 1; for (int i = 1; i <= n; i++) { if (info[i] >= info[i - 1]) dp[i] = dp[i - 1] + info[i] - info[i - 1]; else dp[i] = dp[i - 1]; }
5)打代码
- 首先输入数据。
- 然后按照上面的dp就好了。
- 下面全代码~
AC代码
#include <iostream> #include <algorithm> using namespace std; const int MAX = 1e5 + 7; int info[MAX], dp[MAX]; int main() { int T; cin >> T; while (T--) { int n; cin >> n; for (int i = 1; i <= n; i++) cin >> info[i]; dp[0] = 0; info[0] = 1; for (int i = 1; i <= n; i++) { if (info[i] >= info[i - 1]) dp[i] = dp[i - 1] + info[i] - info[i - 1]; else dp[i] = dp[i - 1]; } cout << dp[n] << endl; } return 0; }
C-面积
啊这
签到题我懂的。
正方向是边长平方,圆是πr2就不用我说了吧。
py再见
AC代码
T = int(input()) for _ in range(T): a = int(input()) r = a / 2 ans = a * a + 2 * 3.14 * r * r print("%.2f" % ans)
E-赛马
1)知识点
这道题是二分,并且可以用STL简化代码。
2)看题目
题目的意思就是叫我们田忌赛马,求最大能赢的比赛。
3)算法分析
- 田忌赛马我们都懂,其实就是选择比对方的马大仅仅一号的马去比赛。
- 所以我们先把我们的马保存下来,然后排个序(这里阔以用STL的multiset,放入自动排序,但是会慢很多),就可以二分找答案了。
- 每次选比这个马大一号的就行了。
4)算法操作
- 我们用multiset保存数据(可自动排序):
for(int i = 0 ; i < n ;++i){ int x; cin >> x; q.insert(x); }
- 然后就可以去二分找答案啦:
int ans = 0; for(int i = 0 ; i < n ;++i){ int x; cin >> x; auto it = upper_bound(q.begin(), q.end(), x); if(it != q.end()){ ++ans; q.erase(it); } }
5)打代码
- 首先STL保存数据。
- 然后按上面二分找答案。
- 下面全代码~
AC代码
#include <iostream> #include <algorithm> #include <set> using namespace std; multiset<int> q; int main(){ int T; cin >> T; while(T--){ q.clear(); int n; cin >> n; for(int i = 0 ; i < n ;++i){ int x; cin >> x; q.insert(x); } int ans = 0; for(int i = 0 ; i < n ;++i){ int x; cin >> x; auto it = upper_bound(q.begin(), q.end(), x); if(it != q.end()){ ++ans; q.erase(it); } } cout << ans << endl; } }
F-三角形
1)知识点
- 递推,就是递推。
2)看题目
- 题目说就是把一个长度为a的可以最多分成几个棒子,使其全不可组成三角形。
3)算法分析
- 首先最小的是1,所以先裁出两个1,然后最小肯定两边之和,就是1 + 1。
- 同理往后,现在有1,1,2,下一个就要1 + 2。我们就看出了这就是个斐波那契。
4)算法操作
- 先初始化斐波那契数列,因为很大,开一个__int128:
for(int i = 3 ; i < 1005 ; ++i) fib[i] = fib[i-1]+fib[i-2];
- 就拿出来判断呗:
for(int i = 3 ; i < 1005 ;++i){ if(fib[i]-1 > a){ ans = i-3; break; } }
5)打代码
- 先初始化斐波那契序列。
- 然后遍历查找就好了。
- 下面全代码~
AC代码
#include <iostream> using namespace std; typedef long long ll; typedef unsigned long long ull; #define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0) const int maxn = 100005; __int128 fib[1005] = {0,1,1}; int main(){ js; for(int i = 3 ; i < 1005 ; ++i) fib[i] = fib[i-1]+fib[i-2]; int T; cin >> T; while(T--){ ull a; cin >> a; if(a < 3){ cout << a << endl; continue; } ll ans; for(int i = 3 ; i < 1005 ;++i){ if(fib[i]-1 > a){ ans = i-3; break; } } cout << ans << endl; } }
H-直线
啊这
你高中学过。
证明我就不证了。看我代码
AC代码
T = int(input()) for _ in range(T): n = int(input()) ans = n * (n - 1) // 2 print(ans)
J-最大值
1)知识点
- 就是kmp嘛
2)看题目
- 题目叫你找一个非前缀的最大的匹配串,可以和前缀最大匹配多长。
3)算法分析
- 其实就是个kmp都能看出来,但是怎么kmp呢?
- 我们kmp其实就是一个对着匹配串原串往后匹配的过程。
- 然后呢我们就可以把原串分为一个原串,一个非前缀串(就是原串去掉第一个字符)。
- 进行一遍匹配,在途中保存最大的匹配长度就好了。
4)算法操作
- 我们的next数组我相信大家都没有问题:
void getnext(char b[]) { int i, j, len = strlen(b); Next[0] = -1; for(i = 0, j = -1; i < len;) if(j == -1 || b[i] == b[j]){ ++i; ++j; if(b[i] != b[j]) Next[i] = j; else Next[i] = Next[j]; } else j = Next[j]; }
- 然后kmp也就是正常匹配,也就是加了一个读最大值而已:
void kmp(char a[],char b[]) { getnext(b); int n = strlen(a); int len = strlen(b); for(int i = 0, j = 0; i < n && j < len;) { if(j == -1 || a[i] == b[j]) { i++, j++; } else j = Next[j], cnt = 0; ans = max(j, ans);//读取最大值 } }
5)打代码
- 先就是输入。
- 然后按上面kmp一下就好了
- 下面全代码~
AC代码
#include <iostream> #include <cstring> using namespace std; typedef long long ll; #define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0) const int maxn = 100005; int cnt = 0, ans = 0; int Next[maxn]; char a[maxn], b[maxn]; void getnext(char b[]) { int i, j, len = strlen(b); Next[0] = -1; for(i = 0, j = -1; i < len;) if(j == -1 || b[i] == b[j]){ ++i; ++j; if(b[i] != b[j]) Next[i] = j; else Next[i] = Next[j]; } else j = Next[j]; } void kmp(char a[],char b[]) { getnext(b); int n = strlen(a); int len = strlen(b); for(int i = 0, j = 0; i < n && j < len;) { if(j == -1 || a[i] == b[j]) { i++, j++; } else j = Next[j], cnt = 0; ans = max(j, ans); } } int main() { IOS; int n; cin >> n; while (n--) { ans = 0; cin >> b; strcpy(a, b + 1); kmp(a, b); cout << ans << endl; } }