没啥好说,都是一遍过
1.求最小公倍数
思路:
求lcm。其实就是两数之乘积除以两个数的gcd。gcd就是是求两个数的最大公约数。
代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);
}int main() {int a, b;cin >> a >> b;cout << (long long)a * b / gcd(a, b) << endl;return 0;
}
2.数组中的最长连续子序列
思路:
题目描述有问题,求的答案跟子序列没半毛钱关系。转换一下题意就是,从一堆数里面选出n个数,这n个数排序后是一个严格+1的递增序列。既然和顺序无关,那就可以先sort.。sort完后用双指针维护一个严格+1的递增区间 。考虑到有重复数字的问题,在此之前去重就好了。
这题其实也可以用dp去做,dp[i]表示以i结尾的最长序列有多长,于是dp[i]=max (dp[i-1]+1 ,dp[i])
这里的dp可以用map维护。
代码:
#define _CRT_SECURE_NO_WARNINGS 1
class Solution {
public:int MLS(vector<int>& arr) {if (arr.size() == 1)return 1;sort(arr.begin(), arr.end());arr.erase(unique(arr.begin(), arr.end()), arr.end());int ans = 0;int i = 1, j = 0;int n = arr.size();for (; i < n; i++) {if (arr[i] - arr[i - 1] != 1) {ans = max(ans, i - j);j = i;}}if (arr[n - 1] - arr[n - 2] == 1) {ans = max(ans, i - j);}return ans;}
};
3.字母收集
思路:
跟杨辉三角没区别。
一般这种dp都是反过来思考的。对于一个(i,j)来说,到达这个点最多有多少分?怎么到达这个点?也就是这个点的上一个状态有哪几种? 只能是dp[i-1][j](表示上面)和dp[i][j-1](左边)来的。所以dp[i][j]就等于这两个状态的最大值。于是轻而易举得到状态转移方程:dp[i][j]=max(dp[i-1][j],dp[i][j-1])+val(arr[i]][j])。注意val表示(i,j)这个点的分数。
简单来说一下对于这种路径dp的思路吧:
假设某种路径问题是,从那里到那里的最大分数啊这种问题。
优先考虑对于当前状态,上一个状态有哪些?
就比如上一道题用dp怎么去想呢?从前往后,到达i这个点的状态有哪些?只能是i-1,所以dp[i]=dp[i-1]+1.
线性dp,区间dp,树上dp基本上都是这么想的。当然具体题目具体的来。
代码:
#include <iostream>
using namespace std;
const int N=510;
char g[N][N];
int f[N][N];int main() {int n,m;cin>>n>>m;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>g[i][j];}} for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){int k=0;if(g[i][j]=='l')k=4;else if(g[i][j]=='o')k=3;else if(g[i][j]=='v')k=2;else if(g[i][j]=='e')k=1;f[i][j]=max(f[i-1][j]+k,f[i][j-1]+k);}}cout<<f[n][m]<<endl;return 0;
}