您的位置:首页 > 游戏 > 手游 > 邢台网站优化建设_企业信息查询公示系统_电脑培训中心_会计培训班要多少钱一般要学多久

邢台网站优化建设_企业信息查询公示系统_电脑培训中心_会计培训班要多少钱一般要学多久

2025/4/19 15:32:42 来源:https://blog.csdn.net/m0_57883655/article/details/146482199  浏览:    关键词:邢台网站优化建设_企业信息查询公示系统_电脑培训中心_会计培训班要多少钱一般要学多久
邢台网站优化建设_企业信息查询公示系统_电脑培训中心_会计培训班要多少钱一般要学多久

比赛链接

A. 智乃的天平

Solution

直接判断是否有 w ∈ { a , b , a + b , ∣ a − b ∣ } . w \in \lbrace a, b, a + b, |a - b| \rbrace. w{a,b,a+b,ab}.

C++ Code

#include <bits/stdc++.h>using i64 = long long;
using u64 = unsigned long long;
using u32 = unsigned;
using i80 = __int128_t;
using u80 = unsigned __int128_t;
using f64 = double;
using f80 = long double;
using i16 = short;
using u16 = unsigned short;constexpr f64 pi = std::numbers::pi;int main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);int a, b, w;std::cin >> a >> b >> w;std::array<int, 4> v{a, b, a + b, std::abs(a - b)};std::cout << (std::ranges::count(v, w) ? "Yes\n": "No\n");return 0;
}

B. 智乃爬山

Solution

直接按照题意模拟求最大值即可。

C++ Code

#include <bits/stdc++.h>using i64 = long long;
using u64 = unsigned long long;
using u32 = unsigned;
using i80 = __int128_t;
using u80 = unsigned __int128_t;
using f64 = double;
using f80 = long double;
using i16 = short;
using u16 = unsigned short;constexpr f64 pi = std::numbers::pi;template<class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {for (auto &x: v) {is >> x;}return is;
}int main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);int n;std::cin >> n;std::vector<int> a(n);std::cin >> a;int ans = -1;for (int i = 1; i + 1 < n; i++) {if (a[i - 1] < a[i] and a[i] > a[i + 1]) {ans = std::max(ans, a[i] - (a[i - 1] + a[i + 1]) / 2);}}std::cout << ans << "\n";return 0;
}

C. 智乃放球

题目大意

给定 m m m 个容量无限大的空桶( ∀ c i = 0 \forall c_i = 0 ci=0)以及一个正整数 k k k。现在做 n n n 轮操作,每轮操作如下:

  • 选定桶 i i i,它有 c i c_i ci 个小球,现在放入一个小球,令 c i : = ( c i + 1 ) ( m o d k ) c_i := (c_i + 1) \pmod k ci:=(ci+1)(modk)

问是否存在一种方案,使得 n n n 次操作结束后有 ∑ i = 1 m c i = q \sum\limits_{i = 1}^{m}c_i = q i=1mci=q

数据范围

  • 1 ≤ T ≤ 1 0 5 , 1 \leq T \leq 10^5, 1T105,
  • 1 ≤ n , m , k ≤ 1 0 9 , 1 \leq n, m, k \leq 10^9, 1n,m,k109,
  • 1 ≤ q ≤ n . 1 \leq q \leq n. 1qn.

Solution

首先, ( n − q ) (n - q) (nq) 一定要是 k k k 的倍数,因为我们最多只能 k k k k k k 个干掉小球。

其次, q ≤ m ⋅ ( k − 1 ) q \leq m\cdot (k - 1) qm(k1),因为一旦数量达到 k k k 就会变为 0 0 0

时间复杂度 O ( T ) O(T) O(T)

C++ Code

#include <bits/stdc++.h>using i64 = long long;
using u64 = unsigned long long;
using u32 = unsigned;
using i80 = __int128_t;
using u80 = unsigned __int128_t;
using f64 = double;
using f80 = long double;
using i16 = short;
using u16 = unsigned short;constexpr f64 pi = std::numbers::pi;std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());void solve() {int n, m, k, q;std::cin >> n >> m >> k >> q;if ((n - q) % k == 0 and q <= static_cast<i64>(k - 1) * m) {std::cout << "Yes\n";} else {std::cout << "No\n";}
}int main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);std::cout << std::fixed << std::setprecision(12);int T = 1;std::cin >> T;while (T--) {solve();}return 0;
}

D. 智乃的“K”叉树

题目大意

给定一棵 n n n 个结点的树,设以第 i ∈ [ 1 , n ] i \in [1, n] i[1,n] 个结点为根的树是 k i k_i ki 叉树,求 min ⁡ i = 1 n k i \min\limits_{i = 1}^{n}k_i i=1minnki 以及对应的 i i i

  • 一棵树为 k k k 叉树,当且仅当存在一个结点 u u u k k k 个儿子;
  • 如果有多个结点满足要求,输出任意一个 i i i

数据范围

  • 2 ≤ n ≤ 1 0 5 . 2 \leq n \leq 10^5. 2n105.

Solution

首先,如果这棵树只有两个结点,那么 k = 1 k = 1 k=1,根随便找 1 1 1 或者 2 2 2 都行。

对于 n > 2 n > 2 n>2 的情况,记录每个结点的度,第 i i i 个结点的度位为 d e g [ i ] \rm{deg[i]} deg[i]

m = max ⁡ i = 1 n ( d e g [ i ] ) > 1 \rm{m = \max\limits_{i = 1}^{n}(deg[i])} > 1 m=i=1maxn(deg[i])>1,我们先把这个最大度对应的 i i i 提到根节点,此时 i i i m m m 个儿子,而剩下的结点最多只有 m − 1 m - 1 m1 个儿子,这是一棵 m m m 叉树。

  • 如果存在一个非根节点 j j j m m m 个儿子,那么加上 j j j j j j 父亲的那条边, j j j 的度就是 m + 1 m + 1 m+1 了,矛盾。

现在找一个结点 j j j 提上来作为新的根结点,要求 d e g [ j ] < m \rm{deg[j]} < m deg[j]<m, 那么这棵新树的度就是 m − 1 m - 1 m1,答案就是 m − 1 m - 1 m1 j j j

  • 首先,这样的结点一定可以找到,比如叶节点;
  • 其次,现在我把 j j j 提上来作为新的根结点,会变化的只有原来的根结点 i i i j j j 这条简单路径上的结点,我们把这个点集记为 S S S
    • j j j 来说,所有与其相连的都成为了它的儿子,因为 j j j 是新的根,这样儿子数量就是 d e g [ j ] < m \rm{deg[j] < m} deg[j]<m
    • 对于 i i i 来说,它在简单路径上的儿子变成了 i i i 的父亲,损失一个儿子,儿子数量变为 m − 1 m - 1 m1
    • 对于 ∀ u ∈ ( S ∖ { j , i } ) \forall u \in (S \setminus \{ j, i \}) u(S{j,i}),都是 u u u 在简单路径上的儿子变成 u u u 的父亲,损失一条儿子边,其他儿子仍然是 u u u 的儿子,而 u u u 在简单路径上的父亲成为 u u u 的儿子,加了一条儿子边,这样总的儿子数保持不变,且由之前的条件可知, u u u 的儿子数均 < m < m <m

时间复杂度 O ( n ) O(n) O(n)

C++ Code

#include <bits/stdc++.h>int main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);int n;std::cin >> n;std::vector<int> deg(n);for (int i = 1; i < n; i++) {int u, v;std::cin >> u >> v;u--, v--;deg[u]++;deg[v]++;}int m = std::ranges::max(deg);if (m == 1) {std::cout << 1 << " " << 1 << "\n";return 0;}int p = std::ranges::find_if(deg, [&](int d) {return d < m;}) - deg.begin();std::cout << m - 1 << " " << p + 1 << "\n";return 0;
}

E/F. 智乃的“凑数”题

题目大意

给定长度为 n n n 的正整数数组 k k k 、正整数 x x x 以及询问次数 m m m,每个询问给出一个 x x x,要求将 k k k 分成两个非空数组 a , b a, b a,b,设长度分别是 n a , n b n_a, n_b na,nb,使得 ∑ i = 1 n a ∑ j = 1 n b ( a i ⋅ b j ) = x , \sum\limits_{i = 1}^{n_a}\sum\limits_{j = 1}^{n_b}(a_i \cdot b_j) = x, i=1naj=1nb(aibj)=x, 问能否实现,如果可以,输出其中一种方案。

数据范围

  • 这里直接上 h a r d \rm{hard} hard 版本的数据范围;
  • 1 ≤ n ≤ 500 , 1 \leq n \leq 500, 1n500,
  • 1 ≤ m ≤ 1000 , 1 \leq m \leq 1000, 1m1000,
  • 1 ≤ k i ≤ 1 0 4 , 1 \leq k_i \leq 10^4, 1ki104,
  • 1 ≤ x ≤ 1 0 4 . 1 \leq x \leq 10^4. 1x104.

Solution

首先题目要求的双层求和其实可以化简。

∑ i = 1 n a ∑ j = 1 n b a i ⋅ b j = ( ∑ i = 1 n a a i ) ( ∑ j = 1 n b b j ) = s a ⋅ s b = x . \sum\limits_{i = 1}^{n_a}\sum\limits_{j = 1}^{n_b}a_i \cdot b_j = \left(\sum\limits_{i = 1}^{n_a}a_i\right)\left( \sum\limits_{j = 1}^{n_b}b_j \right) = \rm{s_a} \cdot s_b = x. i=1naj=1nbaibj=(i=1naai)(j=1nbbj)=sasb=x.

其中 s a , s b s_a, s_b sa,sb 分别表示 a a a 数组的和以及 b b b 数组的和。

s a ⋅ s b = x s_a \cdot s_b = x sasb=x,意味着 s a s_a sa x x x 的因数,所以我们只要考虑枚举 x x x 的因数作为 a a a 数组的和。

d p [ s a ] [ s b ] \rm{dp}[s_a][s_b] dp[sa][sb] 表示能否给 a a a 数组和为 s a s_a sa 的若干个整数,给 b b b 数组和为 s b s_b sb 的若干个整数。

对于当前遍历到的 k i k_i ki 进行状态转移:

  • s a ≥ k i s_a \geq k_i saki,则 d p [ s a ] [ s b ] = d p [ s a ] [ s b ] ∣ ∣ d p [ s a − k i ] [ s b ] \rm{dp[s_a][s_b] = dp[s_a][s_b] \mid \mid dp[s_a - k_i][s_b]} dp[sa][sb]=dp[sa][sb]∣∣dp[saki][sb]
  • s b ≥ k i s_b \geq k_i sbki,则 d p [ s a ] [ s b ] = d p [ s a ] [ s b ] ∣ ∣ d p [ s a ] [ s b − k i ] \rm{dp[s_a][s_b] = dp[s_a][s_b] \mid \mid dp[s_a][s_b - k_i]} dp[sa][sb]=dp[sa][sb]∣∣dp[sa][sbki]

为了最终输出具体的 a , b a, b a,b数组,我们还需要开一个 p r e [ s a ] [ s b ] \rm{pre[s_a][s_b]} pre[sa][sb] 数组记录当前状态是由哪个状态 ( s a ′ , s b ′ ) (s_a', s_b') (sa,sb) 转移而来的。

初值条件: d p [ 0 ] [ 0 ] = t r u e \rm{dp[0][0] = true} dp[0][0]=true

当然,如果直接这样 d p \rm{dp} dp 只能通过 E E E,但在 F F F 题里, x x x 的范围直达 1 0 4 10^4 104,如果开一个 1 0 4 ⋅ 1 0 4 10^4 \cdot 10^4 104104 的数组肯定爆空间了,而且大概率超时,因此要考虑优化。

经过观察,我们发现 s a ⋅ s b = x s_a \cdot s_b = x sasb=x 是在提示我们可以将第二维空间开小一点,例如:

  • s a = 1 s_a = 1 sa=1 时, s b = x s_b = x sb=x
  • s a = 2 s_a = 2 sa=2 时, s b = x 2 s_b = \frac{x}{2} sb=2x
  • s a = 3 s_a = 3 sa=3 时, s b = x 3 s_b = \frac{x}{3} sb=3x
  • ⋯ \cdots

根据级数的知识,当 n n n 较大时, ∑ i = 1 n i ≈ l n n \sum\limits_{i = 1}^{n}i \approx \rm{lnn} i=1nilnn,于是我们可以让第二维 s b s_b sb 动态开,最终的所占总空间的大小大约是 O ( 1 0 4 log ⁡ 1 0 4 ) O(10^4\log 10^4) O(104log104),时间上也够用。

时间复杂度 O ( n V log ⁡ V + m x + m n ) = O ( n V log ⁡ V ) O(nV\log V + m\sqrt{x} + mn) = O(nV\log V) O(nVlogV+mx +mn)=O(nVlogV)

  • V = 1 0 4 V = 10^4 V=104
  • n V log ⁡ V nV\log V nVlogV 表示对每个数都要做一次上述状态转移;
  • m x m\sqrt{x} mx 表示每次询问都要求 x x x 的因数;
  • m n mn mn 表示如果找到了满足条件的 s a , s b s_a, s_b sa,sb,需要根据 p r e \rm{pre} pre 看选了哪些数给 a a a,哪些给 b b b,花费 O ( n ) O(n) O(n)

C++ Code

#include <bits/stdc++.h>using i64 = long long;
using u64 = unsigned long long;
using u32 = unsigned;
using i80 = __int128_t;
using u80 = unsigned __int128_t;
using f64 = double;
using f80 = long double;
using i16 = short;
using u16 = unsigned short;constexpr f64 pi = std::numbers::pi;template<class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {for (auto &x: v) {is >> x;}return is;
}
template<class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {os << v[0];for (size_t i = 1; i < v.size(); i++) {os << " " << v[i];}return os;
}constexpr int U = 10000;int main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);int n, m;std::cin >> n >> m;std::vector<int> k(n);std::cin >> k;std::array<std::vector<std::pair<int, int>>, U + 1> pre{};std::array<std::vector<bool>, U + 1> dp{};for (int r = 0; r <= U; r++) {dp[r].assign(U / std::max(r, 1) + 1, false);pre[r].assign(U / std::max(r, 1) + 1, {});}dp[0][0] = true;for (int v: k) {for (int r = U; r >= 0; r--) {for (int c = U / std::max(r, 1); c >= 0; c--) {if (not dp[r][c]) {continue;}for (auto [dr, dc]: {std::pair {v, 0}, {0, v}}) {if (r + dr <= U and c + dc <= U / std::max(r + dr, 1) and not dp[r + dr][c + dc]) {dp[r + dr][c + dc] = true;pre[r + dr][c + dc] = {r, c};}}}}}while (m--) {int x;std::cin >> x;auto work = [&](int x) {for (int c = 1; c * c <= x; c++) {if (x % c) {continue;}int r = x / c;if (not dp[r][c]) {continue;}std::cout << "Yes\n";std::vector<int> row;std::vector<int> col;for (int x = r, y = c; x > 0 or y > 0; ) {auto [nx, ny] = pre[x][y];if (x != nx) {row.push_back(x - nx);} else {col.push_back(y - ny);}x = nx;y = ny;}std::cout << row.size() << " " << col.size() << "\n";std::cout << row << "\n";std::cout << col << "\n";return true;}return false;};if (not work(x)) {std::cout << "No\n";}}return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com