欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 会展 > Codeforces Round 961 (Div. 2)

Codeforces Round 961 (Div. 2)

2025/5/11 18:54:37 来源:https://blog.csdn.net/2301_80105412/article/details/140653571  浏览:    关键词:Codeforces Round 961 (Div. 2)

A题:Diagonals

题意

给定一个n x n的网格,k个筹码,放在某个位置,则其对应的右上-左下对角线被占用,问占用的对角线数量最少是多少?

思路

模拟

每次我们都往格子最多的对角线上放,然后次多...

很容易看出来

代码

inline void solve() {int n, k; cin >> n >> k;if (k == 0) return cout << 0 << endl, void();if (k - n <= 0) return cout << 1 << endl, void();k -= n;int ans = 2;for (int i = n - 1; i; i -- ) {if (k - i <= 0) return cout << ans << endl, void();k -= i, ans += 1;if (k - i <= 0) return cout << ans << endl, void();k -= i, ans += 1;}return;
}

B1:Bouquet (Easy Version) 

题意

一个小女孩去买花,花店中有n种花,每种花有ai个花瓣

小女孩买来的花束中要求任意两个花瓣数相差不超过1

买ai个花瓣的花,需要ai元,她有m元

问最多花多少元

思路

如果你是用map做的话,B1和B2就会做的飞快)

我们贪心地想,买的多花的也就越多,那么对于t个花瓣的和t+1个花瓣的

我们尽可能地去买t个花瓣的,再去看t+1个花瓣能买多少

但是这再最后一个样例中是错误的

还可以通过少买一个t个花瓣的,多买一个t+1个花瓣的操作,来实现多花一块

那我们只需要先按贪心的来,再看能进行上述操作最多几次即可。

代码

inline ll min(ll a, ll b) {return a > b ? b : a;
}
inline ll max(ll a, ll b) {return a > b ? a : b;
}
inline void solve() {int n; ll k; cin >> n >> k;map<int, int> cnt;for (int i = 1; i <= n; i ++ ) {int x; cin >> x;cnt[x] += 1;}ll ans = 0;for (auto [t, c] : cnt) {ll res = t * min(c, k / t);if (cnt.count(t + 1)) {ll cnt0 = min(c, k / t);ll last = k - res;ll cnt1 = min(last / (t + 1), cnt[t + 1]);res += cnt1 * (t + 1) + min(cnt0, min(cnt[t + 1] - cnt1, last - cnt1 * (t + 1)));}ans = max(ans, res);}cout << ans << endl;return;
}

B2:Bouquet (Hard Version) 

没啥区别,只是对于map的输入改了下而已,笑qwq

代码

inline ll min(ll a, ll b) {return a > b ? b : a;
}
inline ll max(ll a, ll b) {return a > b ? a : b;
}
inline void solve() {int n; ll k; cin >> n >> k;vector<PII> a(n);for (int i = 0; i < n; i ++ ) cin >> a[i].first;for (int i = 0; i < n; i ++ ) cin >> a[i].second;map<int, int> cnt;for (int i = 0; i < n; i ++ ) {cnt[a[i].first] = a[i].second;}ll ans = 0;for (auto [t, c] : cnt) {ll res = t * min(c, k / t);if (cnt.count(t + 1)) {ll cnt0 = min(c, k / t);ll last = k - res;ll cnt1 = min(last / (t + 1), cnt[t + 1]);res += cnt1 * (t + 1) + min(cnt0, min(cnt[t + 1] - cnt1, last - cnt1 * (t + 1)));}ans = max(ans, res);}cout << ans << endl;return;
}

C题:Squaring 

题意

给定一个数组,每次你可以选定一个元素使其成为本身的平方,问至少经过几次操作可以使得整个数组不递减?

思路

平方操作,时间上肯定过的去,但是对于最后一个样例,肯定会爆long long

所以我们的比较,只能是基于ai的本身上

我们可以用一个数组来记录每个位置各用了多少次操作

对于i + 1的位置,若i的位置用了p次操作

a_i^{2^{p}} \leq  a_{i + 1}^{2^{q}}

两边可以不断开方,直到剩到一个数本身ai或者ai+1

即可以为ai <= ai+1的k次  k = q - p    由贪心,k要小

也可以是ai的k次 <= ai      k = p - q    由贪心,k要大

我们通过枚举k就可以知道q,又因为平方增长快,k的枚举范围很小

此外,最后ans将所有次数相加的时候,要开long long,爆了一次...

代码

inline void solve() {int n; cin >> n;vector<ll> a(n + 1);for (int i = 1; i <= n; i ++ ) cin >> a[i];int j = 1;while (j <= n && a[j] == 1) j += 1;vector<int> c(n + 1);for (int i = max(j, 2); i <= n; i ++ ) {if (a[i] == 1) return cout << -1 << endl, void();int k = 0;if (a[i] < a[i - 1]) {ll cur = a[i];while (cur < a[i - 1]) {cur *= cur;k += 1;}c[i] = k + c[i - 1];}else {if (a[i - 1] == 1) continue;ll cur = a[i - 1];while (cur * cur <= a[i]) {cur *= cur;k += 1;}c[i] = max(0, c[i - 1] - k);}}ll ans = 0;for (int i = 1; i <= n; i ++ ) ans += c[i];cout << ans << endl;return;
}

版权声明:

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

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

热搜词