当前位置: 首页 > wzjs >正文

东莞网站优化怎样西安网站seo推广

东莞网站优化怎样,西安网站seo推广,北京模板网站建设,推盟目录 1. Day431.1 kotori和抽卡(二)(概率 - 数学期望)1.2 ruby和薯条(排序 二分 / 双指针)1.3 循环汉诺塔(动态规划) 2. Day442.1 差值(排序)2.2 kotori和素…

目录

  • 1. Day43
    • 1.1 kotori和抽卡(二)(概率 - 数学期望)
    • 1.2 ruby和薯条(排序 + 二分 / 双指针)
    • 1.3 循环汉诺塔(动态规划)
  • 2. Day44
    • 2.1 差值(排序)
    • 2.2 kotori和素因子(DFS)
    • 2.3 dd爱科学1.0(最长上升子序列 - 贪心 + 二分)
  • 3. Day45
    • 3.1 kanan和高音(模拟 + 双指针)
    • 3.2 拜访(BFS)
    • 3.3 买卖股票的最好时机(四)(动态规划)
  • 4. Day46
    • 4.1 AOE还是单体?(贪心)
    • 4.2 kotori和n皇后(哈希表)
    • 4.3 取金币(动态规划 - 区间dp)
  • 5. Day47
    • 5.1 矩阵转置(数学)
    • 5.2 四个选项(DFS + 剪枝 + 哈希表)
    • 5.3 接雨水问题(双指针)
  • 6. Day48
    • 6.1 疯狂的自我检索者(贪心)
    • 6.2 栈和排序(栈 + 贪心)
    • 6.3 加减(枚举 + 前缀和 + 滑动窗口 + 贪心)

1. Day43

1.1 kotori和抽卡(二)(概率 - 数学期望)

  1. 题目链接: kotori和抽卡(二)
  2. 题目描述:

  1. 解法:
    • 算法思路:直接代入高中求概率的公式~
  2. C++ 算法代码:
#include <iostream>
using namespace std;int main()
{int n, m;cin >> n >> m;double ret = 1.0;for(int i = 0; i < m; i++){ret *= 0.8;}for(int i = 0; i < n - m; i++){ret *= 0.2;}for(int i = n; i >= n - m + 1; i--){ret *= i;}for(int i = m; i >= 2; i--){ret /= i;}printf("%.4lf", ret);return 0;
}

1.2 ruby和薯条(排序 + 二分 / 双指针)

  1. 题目链接: ruby和薯条
  2. 题目描述:

  1. 解法:
    • 算法思路:
      • 解法⼀:排序 + 二分。 先排序,然后枚举较大值,在 [1, i - 1] 区间找差值的左右端点即可。
      • 解法二:排序 + 前缀和 + 双指针。 先排序;求差值在 [L, R] 区间内数对的个数,可以转化成求 [0, R] 区间内的个数 - [0, L] 区间内的个数。其中求 [0, X] 区间内数对的个数,可以用双指针快速统计出以 arr[right] 为结尾的数对有多少个。
  2. C++ 算法代码:
// 解法⼀:排序 + ⼆分
#include <iostream>
#include <algorithm>
using namespace std;const int N = 2e5 + 10;int main()
{int n, l, r;cin >> n >> l >> r;int arr[N];for(int i = 1; i <= n; i++){cin >> arr[i];}sort(arr + 1, arr + n + 1);long long ret = 0;for(int i = 2; i <= n; i++){int L, R;// 找左端点int left = 1;int right = i - 1;while(left < right){int mid = (right + left) / 2;if(arr[mid] >= arr[i] - r){right = mid;}else{left = mid + 1;}}if(arr[left] >= arr[i] - r){L = left;}else{L = left + 1;}// 找右端点left = 1;right = i - 1;while(left < right){int mid = (right + left + 1) / 2;if(arr[mid] <= arr[i] - l){left = mid;}else{right = mid - 1;}}if(arr[left] <= arr[i] - l){R = left;}else{R = left - 1;}if(R >= L){ret += R - L + 1;}}cout << ret << endl;return 0;
}// 解法⼆:排序 + 前缀和 + 滑动窗⼝
#include <iostream>
#include <algorithm>
using namespace std;const int N = 2e5 + 10;
int n, l, r;
int arr[N];// 找出差值在 [0, x] 之间⼀共有多少对
long long find(int x)
{int left = 0, right = 0;long long ret = 0;while(right < n){while(arr[right] - arr[left] > x){left++;}ret += right - left;right++;}return ret;
}
int main()
{cin >> n >> l >> r;for(int i = 0; i < n; i++) cin >> arr[i];sort(arr, arr + n);cout << find(r) - find(l - 1) << endl;return 0;
}

1.3 循环汉诺塔(动态规划)

  1. 题目链接: AB27 循环汉诺塔
  2. 题目描述:

  1. 解法:
    • 算法思路:动态规划 + 空间优化。
    • 规律如下:AB(1)= 1,AC(1)= 2,AB(N)= 2 * AC(N-1)+ 1,AC(N)= 2 * AC(N-1)+ AB(N-1)+ 2
  2. C++ 算法代码:
#include <iostream>
using namespace std;const int MOD = 1e9 + 7;int main() 
{int n = 0;cin >> n;int x = 1;int y = 2;for(int i = 2; i <= n; i++){int xx = x, yy = y;x = (2 * yy + 1) % MOD;y = ((2 * yy) % MOD + 2 + xx) % MOD;}cout << x << " " << y << endl;return 0;
}

2. Day44

2.1 差值(排序)

  1. 题目链接: 最小差值
  2. 题目描述:

  1. 解法:
    • 算法思路:排序,然后计算相邻两个数之差的最小值即可。
  2. C++ 算法代码:
class Solution {
public:int minDifference(vector<int>& a) {sort(a.begin(), a.end());long long ret = 1e16 + 10;;for(int i = 1; i < a.size(); i++){ret = min(ret, (long long)a[i] - a[i - 1]);}return ret;}
};

2.2 kotori和素因子(DFS)

  1. 题目链接: kotori和素因子
  2. 题目描述:

  1. 解法:
    • 算法思路:递归型枚举所有的情况。
  2. C++ 算法代码:
#include <iostream>
#include <cmath>
using namespace std;const int N = 15, M = 1010;
int n = 0;
int arr[N] = {0};
bool use[M]; // 记录路径中⽤了哪些值
int path; // 记录当前路径中所有元素的和
int ret = 0x3f3f3f3f; // 统计最终结果bool isPrim(int x)
{if(x <= 1){return false;}for(int i = 2; i <= sqrt(x); i++){if(x % i == 0){return false;}}return true;
}void dfs(int pos)
{if(pos == n){ret = min(ret, path);}for(int i = 2; i <= arr[pos]; i++){if(arr[pos] % i == 0 && isPrim(i) && !use[i]){path += i;use[i] = true;dfs(pos + 1);// 回溯 - 恢复现场path -= i;use[i] = false;}}
}int main()
{cin >> n;for(int i = 0; i < n; i++){cin >> arr[i];}dfs(0);if(ret == 0x3f3f3f3f){cout << -1 << endl;}else{cout << ret << endl;}return 0;
}

2.3 dd爱科学1.0(最长上升子序列 - 贪心 + 二分)

  1. 题目链接: dd爱科学1.0
  2. 题目描述:

  1. 解法:
    • 算法思路:
      • 要想改动最小,就应该在最长非下降子序列的基础上,对不是最长的部分进行更换。
      • 因为这道题的数据范围比较大,所以应该用贪心 + 二分求出最长非下降子序列的长度。
  2. C++ 算法代码:
#include <iostream>
using namespace std;const int N = 1e6 + 10;int main()
{int n = 0;string s;cin >> n >> s;char dp[N]; // dp[i] 表⽰:⻓度为 i 的所有的⼦序列中,最⼩的末尾是多少int ret = 0;for(int i = 0; i < n; i++){char ch = s[i];if(ret == 0 || dp[ret] <= ch){dp[++ret] = ch;}else{// ⼆分出 ch 应该放的位置int left = 1;int right = ret;while(left < right){int mid = (left + right) / 2;if(dp[mid] > ch){right = mid;}else{left = mid + 1;}}dp[left] = ch;}}cout << n - ret << endl;return 0;
}

3. Day45

3.1 kanan和高音(模拟 + 双指针)

  1. 题目链接: kanan和高音
  2. 题目描述:

  1. 解法:
    • 算法思路:从前往后遍历,用双指针找出⼀段能唱完的区域,然后更新指针继续找下⼀段。
  2. C++ 算法代码:
#include <iostream>
using namespace std;const int N = 2e5 + 10;
int n;
int arr[N];int main()
{cin >> n;for(int i = 0; i < n; i++){cin >> arr[i];}int ret = 1;int left = 0;while(left < n){int right = left;while(right + 1 < n && arr[right + 1] - arr[right] <= 8){right++;}ret = max(ret, right - left + 1);left = right + 1;}cout << ret << endl;return 0;
}

3.2 拜访(BFS)

  1. 题目链接: MT3 拜访
  2. 题目描述:

  1. 解法:
    • 算法思路:在层序遍历的过程中,维护额外的信息。
  2. C++ 算法代码:
class Solution {
public:int x1, y1, x2, y2;int dist[15][15] = { 0 };   // 判断是否经过int cnt[15][15] = { 0 };    // 到改位置的最短路径的数量int dx[4] = {0, 0, 1, -1};int dy[4] = {1, -1, 0, 0};int bfs(vector<vector<int> >& CityMap, int n, int m){memset(dist, -1, sizeof dist);queue<pair<int, int>> q;q.push({x1, y1});dist[x1][y1] = 0;cnt[x1][y1] = 1;while(q.size()){auto [a, b] = q.front();q.pop();for(int i = 0; i < 4; i++){int x = a + dx[i];int y = b + dy[i];if(x >= 0 && x < n && y >= 0 && y < m && CityMap[x][y] != -1){if(dist[x][y] == -1)    // 第⼀次到这个位置{dist[x][y] = dist[a][b] + 1;cnt[x][y] += cnt[a][b];q.push({x, y});}else {if(dist[a][b] + 1 == dist[x][y]) // 是不是最短路{cnt[x][y] += cnt[a][b];}}}}}return cnt[x2][y2];}int countPath(vector<vector<int> >& CityMap, int n, int m) {for(int i = 0; i < n; i++){for(int j = 0; j < m; j++){if(CityMap[i][j] == 1){x1 = i;y1 = j;}else if(CityMap[i][j] == 2){x2 = i;y2 = j;}}}return bfs(CityMap, n, m);}
};

3.3 买卖股票的最好时机(四)(动态规划)

  1. 题目链接: DP33 买卖股票的最好时机(四)
  2. 题目描述:

  1. 解法以及算法思路:
    1. 状态表示:为了更加清晰的区分「买入」和「卖出」,我们换成「有股票」和「无股票」两个状态。
      • f[i][j] 表示:第 i 天结束后,完成了 j 笔交易,此时处于「有股票」状态的最大收益;
      • g[i][j] 表示:第 i 天结束后,完成了 j 笔交易,此时处于「无股票」状态的最大收益。
    2. 状态转移方程:
      • 对于 f [i][j] ,我们也有两种情况能在第 i 天结束之后,完成 j 笔交易,此时手里「有股票」的状态:
        • 在 i - 1 天的时候,手里「有股票」,并且交易了 j 次。在第 i 天的时候,啥也不干。此时的收益为 f[i - 1][j] ;
        • 在 i - 1 天的时候,手里「没有股票」,并且交易了 j 次。在第 i 天的时候,买了股票。那么 i 天结束之后,我们就有股票了。此时的收益为 g[i - 1][j] - prices[i] ;
        • 上述两种情况,我们需要的是「最大值」,因此 f 的状态转移方程为: f[i][j] = max(f[i - 1][j], g[i - 1][j] - prices[i])
      • 对于 g [i][j] ,我们有下面两种情况能在第 i 天结束之后,完成 j 笔交易,此时手里「没有股票」的状态:
        • 在 i - 1 天的时候,手里「没有股票」,并且交易了 j 次。在第 i 天的时候,啥也不干。此时的收益为 g[i - 1][j] ;
        • 在 i - 1 天的时候,手里「有股票」,并且交易了 j - 1 次。在第 i 天的时候,把股票卖了。那么 i 天结束之后,我们就交易了 j 次。此时的收益为 f[i - 1][j - 1] + prices[i] ;
        • 上述两种情况,我们需要的是「最大值」,因此 g 的状态转移方程为: g[i][j] = max(g[i - 1][j], f[i - 1][j - 1] + prices[i])
    3. 初始化:
      • 由于需要用到 i = 0 时的状态,因此我们初始化第一行即可。
      • 当处于第 0 天的时候,只能处于「买入过⼀次」的状态,此时的收益为 -prices[0] ,因此 f[0][0] = - prices[0] 。
      • 为了取 max 的时候,⼀些不存在的状态「起不到干扰」的作用,我们统统将它们初始化为 - INF (用 INT_MIN 在计算过程中会有「溢出」的风险,这里 INF 折半取 0x3f3f3f3f ,足够小即可)。
    4. 填表顺序:
      • 从上往下填每⼀行,每⼀行从左往右,两个表⼀起填。
    5. 返回值:
      • 返回处于卖出状态的最大值,但是我们也不知道是交易了几次,因此返回 g 表最后⼀行的最大值。
    6. 优化点:
      • 我们的交易次数是不会超过整个天数的⼀半的,因此我们可以先把 k 处理⼀下,优化⼀下问题的规模:k = min(k, n / 2)。
    7. 如果画一个图的话,它们之间交易关系如下:

  1. C++ 算法代码:
#include <iostream>
using namespace std;const int N = 1010, M = 110;
int n, k, p[N];
int f[N][M], g[N][M];int main() 
{cin >> n >> k;for(int i = 0; i < n; i++){cin >> p[i];}k = min(k, n / 2);for(int j = 0; j <= k; j++){f[0][j] = g[0][j] = -0x3f3f3f3f;}f[0][0] = -p[0];g[0][0] = 0;for(int i = 1; i < n; i++){for(int j = 0; j <= k; j++){f[i][j] = max(f[i - 1][j], g[i - 1][j] - p[i]);g[i][j] = g[i - 1][j];if(j >= 1){g[i][j] = max(g[i][j], f[i - 1][j - 1] + p[i]);}}}int ret = 0;for(int j = 0; j <= k; j++){ret = max(ret, g[n - 1][j]);}cout << ret << endl;return 0;
}

4. Day46

4.1 AOE还是单体?(贪心)

  1. 题目链接: AOE还是单体?
  2. 题目描述:

  1. 解法:
    • 算法思路。小贪心:
      • 如果使用一次 AOE 造成的伤害比消耗的蓝量多,那就使用;
      • 否则就一直使用单体伤害。
  2. C++ 算法代码:
#include <iostream>
#include <algorithm>
using namespace std;const int N = 2e5 + 10;int main()
{int n, x;cin >> n >> x;int arr[N];for(int i = 1; i <= n; i++){cin >> arr[i];}sort(arr + 1, arr + n + 1);long long ret = 0;int index = max(0, n - x);ret += arr[index] * x;for(int i = index + 1; i <= n; i++){ret += arr[i] - arr[index];}cout << ret << endl;return 0;
}

4.2 kotori和n皇后(哈希表)

  1. 题目链接: kotori和n皇后
  2. 题目描述:

  1. 解法:
    • 算法思路:使用哈希表标记行列以及两个对角线。
  2. C++ 算法代码:
#include <iostream>
#include <unordered_set>
using namespace std;int k, t;
int ret = 1e5 + 10; // 第⼀次出现互相攻击的皇后的个数
unordered_set<long long> row; // 标记⾏ y
unordered_set<long long> col; // 标记列 x
unordered_set<long long> dig1; // 标记主对⻆线 y - x
unordered_set<long long> dig2; // 标记副对⻆线 y + xint main()
{cin >> k;for(int i = 1; i <= k; i++){int x, y;cin >> x >> y;if(ret != 1e5 + 10){continue;}if(row.count(y) || col.count(x) || dig1.count(y - x) || dig2.count(y + x)){ret = i;}row.insert(y); col.insert(x);dig1.insert(y - x);dig2.insert(y + x);}cin >> t;while(t--){int i = 0;cin >> i;if(i >= ret){cout << "Yes" << endl;}else{cout << "No" << endl;}}return 0;
}

4.3 取金币(动态规划 - 区间dp)

  1. 题目链接: NC393 取金币
  2. 题目描述:

  1. 解法:
    • 算法思路。区间 dp:
      • 为了方便能处理边界情况,将原数组前后添加⼀个 1,并不影响最后的结果。
      • 状态表示:
        • dp[i][j] 表示: [i, j] 区间⼀共能获得多少金币。
  2. C++ 算法代码:
class Solution {
public:int arr[110] = { 0 };int dp[110][110] = { 0 };int getCoins(vector<int>& coins) {int n = coins.size();arr[0] = arr[n + 1] = 1;for(int i = 1; i <= n; i++){arr[i] = coins[i - 1];}for(int i = n; i >= 1; i--){for(int j = i; j <= n; j++){for(int k = i; k <= j; k++){dp[i][j] = max(dp[i][j], dp[i][k - 1] + dp[k + 1][j] + arr[i - 1] * arr[k] * arr[j + 1]);}}}return dp[1][n];}
};

5. Day47

5.1 矩阵转置(数学)

  1. 题目链接: BC138 矩阵转置
  2. 题目描述:

  1. 解法:
    • 算法思路:观察转置前和转置后下标的关系即可。
  2. C++ 算法代码:
#include <iostream>
using namespace std;const int N = 15;
int n, m;
int arr[N][N];int main() 
{cin >> n >> m;for(int i = 0; i < n; i++){for(int j = 0; j < m; j++){cin >> arr[i][j];}}for(int j = 0; j < m; j++){for(int i = 0; i < n; i++){cout << arr[i][j] << " ";}cout << endl;}return 0;
}

5.2 四个选项(DFS + 剪枝 + 哈希表)

  1. 题目链接: 四个选项
  2. 题目描述:

  1. 解法:
    • 算法思路:用递归枚举出所有的情况,注意剪枝。
  2. C++ 算法代码:
#include <iostream>
#include <vector>
using namespace std;int cnt[5]; // ⽤数组存每⼀个选项出现多少次
int m, x, y;
bool same[13][13]; // 存哪些题的答案是相同的
int ret;
vector<int> path; // 记录路径⾥⾯选了哪些选项bool isSame(int pos, int cur)
{for(int i = 1; i < pos; i++){if(same[pos][i] && path[i] != cur){return false;}}return true;
}void dfs(int pos)
{if(pos > 12){ret++;return;}for(int i = 1; i <= 4; i++){if(cnt[i] == 0)  // 没有使⽤次数{continue;}if(!isSame(pos, i))  // 需要相同的位置,没有相同{continue;}cnt[i]--;path.push_back(i);dfs(pos + 1);path.pop_back();cnt[i]++;}
}int main()
{for(int i = 1; i <= 4; i++){cin >> cnt[i];}cin >> m;while(m--){cin >> x >> y;same[x][y] = same[y][x] = true;}path.push_back(0); // 先放进去⼀个占位符dfs(1);cout << ret << endl;return 0;
}

5.3 接雨水问题(双指针)

  1. 题目链接: 接雨水
  2. 题目描述:

  1. 解法:
    • 算法思路:考虑每一根柱子上方雨水的高度。
  2. C++ 算法代码:
class Solution {
public:int trap(vector<int>& height) {int n = height.size();vector<int> left(n);vector<int> right(n);left[0] = height[0];for(int i = 1; i < n; i++){left[i] = max(left[i - 1], height[i]);}right[n - 1] = height[n - 1];for(int i = n - 2; i >= 0; i--){right[i] = max(right[i + 1], height[i]);}int ret = 0;for(int i = 1; i < n - 1; i++){ret += min(left[i], right[i]) - height[i];}return ret;}
};

6. Day48

6.1 疯狂的自我检索者(贪心)

  1. 题目链接: 疯狂的自我检索者
  2. 题目描述:

  1. 解法:
    • 算法思路:小贪心~
  2. C++ 算法代码:
#include <iostream>
using namespace std;int main()
{int n, m, a;cin >> n >> m;int sum = 0;for(int i = 0; i < n - m; i++){cin >> a;sum += a;}printf("%.5lf %.5lf\n", (sum + m) * 1.0 / n, (sum + m * 5) * 1.0 / n);return 0;
}

6.2 栈和排序(栈 + 贪心)

  1. 题目链接: NC115 栈和排序
  2. 题目描述:

  1. 解法:
    • 算法思路:每次尽可能的先让当前需要的最大值弹出去。
  2. C++ 算法代码:
#include <stack>
class Solution {
public:vector<int> solve(vector<int>& a) {int n = a.size();stack<int> st;bool hash[50010] = { 0 }; // 统计当前哪些元素已经进栈int aim = n;vector<int> ret;for(auto& x : a){st.push(x);hash[x] = true;while(hash[aim]){aim--;}while(st.size() && st.top() >= aim){ret.push_back(st.top());st.pop();}}return ret;}
};

6.3 加减(枚举 + 前缀和 + 滑动窗口 + 贪心)

  1. 题目链接: 加减
  2. 题目描述:

  1. 解法:
    • 算法思路:转化问题。将原数组排序之后,选择⼀段区间,让他们在不超过 k 次的前提下,全部变的相等。
  2. C++ 算法代码:
#include <iostream>
#include <algorithm>
using namespace std;const int N = 1e5 + 10;
long long n, k;
long long arr[N];
long long sum[N] = {0}; // 前缀和数组long long cal(int l, int r)
{int mid = (l + r) / 2;return (mid - l - r + mid) * arr[mid] - (sum[mid - 1] - sum[l - 1]) + (sum[r] - sum[mid]);
}int main()
{cin >> n >> k;for(int i = 1; i <= n; i++){cin >> arr[i];}sort(arr + 1, arr + n + 1);for(int i = 1; i <= n; i++){sum[i] = sum[i - 1] + arr[i];}int left = 1;int right = 1;int ret = 1;while(right <= n){long long cost = cal(left, right);while(cost > k){left++;cost = cal(left, right);}ret = max(ret, right - left + 1);right++;}cout << ret << endl;return 0;
}
http://www.dtcms.com/wzjs/144361.html

相关文章:

  • b2c网站比较电商网站规划
  • 网站色差表全网营销系统
  • 天津网站建设哪家好如何在百度发广告推广
  • dede做漫画网站的案例营销软文范例500
  • 如何用手机做网页seo优化教程自学网
  • 政务网站开发武汉seo创造者
  • wordpress 速度很慢马鞍山seo
  • 新疆示范工程建设服务平台网站哪个平台可以接推广任务
  • 建设网站出现400错误自媒体发稿
  • 网站焦点图如何美观广州seo诊断
  • c语言 做网站网站老域名跳转到新域名
  • 网站开发后端做那些国通快速建站
  • 深圳网站建设卓企成都全网营销推广
  • 中小企业网站提供了什么成品网站seo
  • ftp怎么连接网站空间兰州seo整站优化服务商
  • 平度那里有做网站的百度关键词刷排名软件
  • 淘宝客优惠卷网站模板提高工作效率的软件
  • 做一个商城网站需要提交那些文件seo百科大全
  • 装修公司做推广网站怎么弄网站优化塔山双喜
  • 做网站从何开始最近的新闻大事20条
  • 东莞做企业网站友情下载网站
  • 七里港网站建设互联网推广渠道有哪些
  • 外链的论坛网站站长统计幸福宝下载
  • 佛山外贸网站制作公司最新军事报道
  • 电白网站开发公司网站推广优化教程
  • 有了云服务器怎么做网站百度服务中心电话
  • 购物网站及app开发黄冈seo顾问
  • 百度seo排名点击seo推广营销靠谱
  • 官方网站开发商seo的方式包括
  • php网站开发建设seo关键词怎么选