首页 > 其他分享 >3 月 8 日测试题解

3 月 8 日测试题解

时间:2023-03-12 15:24:14浏览次数:42  
标签:std le 测试题 int double long Delta

3 月 8 日测试题解

T1

题意

给你一张图 \(G = (V, E)\),\(|V| = n\),\(|E| = m\),带边权、点权。你可以执行以下操作任意多次:

  • 选取一个顶点,将其自身与与其相连的边删去

当你结束操作时,得到一张新图 \(G' = (V', E')\),你需要保证 \(n' \ge 2\),并且图联通。

现在求下面这个式子的值:

\[\max{(\frac{\sum_{v \in V'} w(v)}{\sum_{e \in E'} w(e)})} \]

对于 \(20\%\) 的数据,\(n = 2\);
对于 \(50\%\) 的数据,\(n \le 5\);
对于 \(100\%\) 的数据,\(n \le 10^5\)。

思路

\(\text{20pts}\)

只有一条边,用脚趾头都写的出来。

\(\text{50pts}\)

考虑 DSU + 二进制枚举,倒着做,每次枚举一条边的两个顶点是否加入图中,这样可以保证图联通。

\(\text{100pts}\)

本题为结论题,结论就是最优的解一定只包含两个顶点。

为了证明这个结论,我们令 \(S_v\) 为当前选出的最优点权和,\(S_e\) 为当前选出的最优边权和,\(\Delta v\) 为将要加入的点权和,\(\Delta e\) 为将要加入的边权和。

如果更优的话,那么我们有:

\[\frac{S_v}{S_e} \le \frac{S_v + \Delta v}{S_e + \Delta e} \]

\[S_v(S_e + \Delta e) \le S_e(S_v + \Delta v) \]

\[S_v \Delta e \le S_e \Delta v \]

也就是:

\[\frac{S_v}{S_e} \le \frac{\Delta v}{\Delta e} \]

又:

\[\frac{S_v}{S_e} \le \frac{S_v + \Delta v}{S_e + \Delta e} \le \frac{\Delta v}{\Delta e} \]

也就意味着你不如舍弃之前的,直接选 \(\Delta v\) 所对应的那个点。这样一番操作下来,你最终只能选两个点。

感觉证明有点假?凑合着看吧。

代码

\(\text{100pts}\)

#include <bits/stdc++.h>

using i64 = long long;

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(0);

  int n, m;
  std::cin >> n >> m;
  
  std::vector<int> a(n);
  for (auto &i : a) {
    std::cin >> i;
  }

  double ans = 0;
  for (int i = 1; i <= m; i++) {
    int u, v, w;
    std::cin >> u >> v >> w;
    ans = std::max(ans, double(a[u - 1] + a[v - 1]) / w);
  }

  std::cout << std::fixed << std::setprecision(2) << ans << "\n";

  return 0;
}

T2

题意

四个数组 \(A\),\(B\),\(C\),\(D\) 和一个整数 \(n\)。现从四个数组中各取一个数字,询问有多少种方案使得这四个数的和不超过 \(n\)。

对于 \(30\%\) 的数据,\(|A|,|B|,|C|,|D| \le 50\);
对于另 \(30\%\) 的数据,\(n \le 1000\);
对于 \(100\%\) 的数据,\(n \le 10^8\),\(|A|,|B|,|C|,|D| \in [1, 5000]\),\(A_i, B_i, C_i, D_i \in [0, 10^8]\)。

思路

\(\text{30pts}\)

此时数组的范围都比较小,考虑直接枚举,四重循环,时间复杂度为 \(O(|A| |B||C||D|)\)。

\(\text{60pts \& 100pts}\)

这道题 \(\text{60pts}\) 与 \(\text{100pts}\) 的做法应该是一样的。

考虑常见优化:折半。开两个桶 \(b_1\) 与 \(b_2\),\(b_1\) 存储 \(A\) 与 \(B\) 中的和,\(b_2\) 存储 \(C\) 与 \(D\) 中的和。也就是说:

\[b_{1,i} = \sum_{i \in A, j \in B} {[i +j \le n]} \]

\[b_{2,i} = \sum_{i \in C, j \in D} {[i +j \le n]} \]

然后考虑对其中一个做前缀和,这里我们假设是 \(b_1\)。那么最终的答案就是:

\[\sum_{i = 0}^{n} {b_{1, n - i}b_{2, i}} \]

时间复杂度为 \(O(|A||B| + |C||D| + n)\)。评价是能过就行,而且这个题也没有更优的做法了。

代码

#include <bits/stdc++.h>

using i64 = long long;

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(0);
  
  int n;
  std::vector<int> num(4);
  std::cin >> n;
  for (auto &i : num) {
    std::cin >> i;
  }
  
  std::vector<int> l[4];
  for (int i = 0; i < 4; i++) {
    l[i].resize(num[i]);
    for (auto &j : l[i]) {
      std::cin >> j;
    }
  }
  
  std::vector<i64> lo(n + 1, 0), hi(n + 1, 0);
  for (auto &i : l[0]) {
    for (auto &j : l[1]) {
      if (i + j > n) {
        continue;
      }
      lo[i + j]++;
    }
  }
  for (auto &i : l[2]) {
    for (auto &j : l[3]) {
      if (i + j > n) {
        continue;
      }
      hi[i + j]++;
    }
  }
  
  i64 ans = 0;
  for (int i = 1; i <= n; i++) {
    lo[i] += lo[i - 1];
  }
  for (int i = 0; i <= n; i++) {
    ans += hi[i] * lo[n - i];
  }
  
  std::cout << ans << "\n";
  
  return 0;
}

T3

题意

数轴上有 \(n\) 个动点,其中每个动点 \(\widetilde{P}\) 有两个属性:开始移动的时间 \(t_P\) 与速度 \(v_P\)。现在问在所有的点都开始移动后,处于第一的点与最后的点的距离最小值是多少。

\(n \le 100000\)。

思路

\(\text{100pts}\)

我们知道这道题的正解是三分法,但是有没有想过这个函数为什么是单谷函数?

证 nm 我不证了,评价是我想过但是想不出来,自己都不知道为什么是对的还要强迫我写题解?

反正就是你猜它是一个单谷函数,然后代进去发现很正确,注意一下细节然后就做完了。

从这道题得到的唯一收获就是:看到这种求最值的问题,先猜结论。

代码

#include <bits/stdc++.h>

using i64 = long long;

struct Node {
  int t, v;
  Node() {
    t = 0, v = 0;
    return;
  }
};

long double calc(long double mid, std::vector<Node> a) {
  long double minn, maxx;
  minn = (mid - a[0].t) * a[0].v;
  maxx = minn;

  for (int i = 1; i < a.size(); i++) {
    long double tmp = (mid - a[i].t) * a[i].v;
    minn = std::min(minn, tmp);
    maxx = std::max(maxx, tmp);
  }

  return maxx - minn;
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(0);

  static const long double EPS = 1e-12;

  int n;
  std::cin >> n;

  long double l = 0, r = 1e15;

  std::vector<Node> a(n); 
  for (int i = 0; i < n; i++) {
    std::cin >> a[i].t >> a[i].v;
    l = std::max(l, (long double) a[i].t);
  }

  while (r - l > EPS) {
    long double lmid = l + (r - l) / 3, rmid = r - (r - l) / 3;
    std::cerr << lmid << " " << rmid << "\n";
    if (calc(lmid, a) < calc(rmid, a) + EPS) {
      r = rmid;
    } else {
      l = lmid;
    }
  }

  std::cout << std::fixed << std::setprecision(2) << calc(l, a) << "\n";

  return 0;
}

标签:std,le,测试题,int,double,long,Delta
From: https://www.cnblogs.com/forgot-dream/p/17208197.html

相关文章

  • 3.2 L5-NOIP训练29 测试题解
    3.2L5-NOIP训练29测试题解码创Contest#530(出题人写中文也要句句都打分号吗!!)A.老司机的压缩包(数论)题面老司机最近得到了一个奇怪的压缩包,听说里面有十分厉害的东西......
  • 3 月 1 日测试题解
    3月1日测试题解T1题意给你一个\(n\timesm\)的01矩形,求一个面积最大的不包含数字1的矩形。\(n,m\le1000\)。思路首先,这道题的数据水到了什么程度呢?\(O(n......
  • 今日课上测试题总结-计算最长英语单词链
    今天软工课上老师留的作业总结一下1importjava.io.*;2importjava.util.*;34publicclassMaxlist{56publicstaticvoidmain(String[]args)th......
  • L5-NOIP模拟11 测试题解
    经典老题排名-L5-NOIP模拟11-码创未来A.[CQOI2009]中位数洛谷P1627|码创未来题意给出\(1,2,\dots,n\)的一个排列,统计该排列有多少个长度为奇数的连续子串......
  • 部分互测题,专项测试题题解
    互测部分1https://www.cnblogs.com/Chencgy/p/16970117.html2A.营救皮卡丘跑弗洛伊德,搞出\(i->j\)不经过比\(i,j\)编号大的点的最小花费每个点都要走一遍,套......
  • 万喜人《平面几何测试题集》题记
    更新到测试9暂时做的不是很好,日后完善常规题目通过倒角,全等,相似常规辅助线模块构型中的初级知识可以完成的题目[1]1,2,5(同一法)[2]1[3]1,2(等角共轭点),3......
  • JAVA结业测试题及答案
    JAVA结业试题二1下列哪些方法互为重载方法,哪些方法是覆盖方法。答案用号码标识:4分publicclassA{  ①publicstaticvoidmethod(Stringstr){};  ②protected int......
  • 软件测试题库小程序推荐 这个免费题库,你用绝对停不下来
    对于已经掌握了如测试基础技能的人来说,最需要的就是进入到软件测试岗位上去工作,但由于面试是从业者必须经历的一个环节,而很多测试人因为也是才好踏入测试边缘,并没有相关的岗......
  • 数据结构与算法测试题
    1.完全二叉树的第5层有9个节点,该完全二叉树总计有多少个节点( B   ).A.41B.24C.40D.25完全二叉树,说明前四层都是满结点,第五层有九个结点,故有:2^4 -1=15     ......
  • 操作系统 测试题
    一、单选1、下面哪项不是常用调度算法A、FCFS B、SJF C、HRN D、ABC2、响应比的计算方法是A、(作业等待时间+作业执行时间)/作业执行时间B、(作业等待时间+作业执行时间)/......