A组Day7

A. 放置石子

image-20231118181321618

我们设第一格的东西为 x ,则接下来的格数为

21+x32x+143x+255x+3...

易得x的系数就是原来的斐波那契额数列,而后面加上来的也是!我们可以打表

image-20231118181709287

左边为系数表,右边为加的数表

#include <bits/stdc++.h> using namespace std; typedef long long ll; ll xs[21] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765}; ll k[21] = {1, 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181}; int main() { freopen("kela.in", "r", stdin); freopen("kela.out", "w", stdout); long long a, x, b; while (cin >> a >> x >> b) { if ((x - k[a]) % xs[a] == 0) printf("%lld\n", (x - k[a]) / xs[a] * xs[b] + k[b]); else puts("-1"); } return 0; }

B.连通块数

image-20231118181811876

暴力进行dfs即可,这里注意,每次进行dfs的时候都要扩展完毕,然后后面一遇到没扩展的就扩展

#include <bits/stdc++.h> using namespace std; const int N = 55; int l, w, h, m; int dx[7] = {0, 0, 0, 0, 0, 1, -1}; int dy[7] = {0, 0, 0, -1, 1, 0, 0}; int dz[7] = {0, 1, -1, 0, 0, 0, 0}; int a[N][N][N]; bool vis[N][N][N]; int ans = 0; void dfs(int x, int y, int z) { for (int i = 1; i <= 6; i++) { int tx = x + dx[i], ty = y + dy[i], tz = z + dz[i]; if (tx < 1 || tx > l || ty < 1 || ty > w || tz < 1 || tz > h || vis[tx][ty][tz]) continue; if (abs(a[x][y][z] - a[tx][ty][tz]) <= m) { vis[tx][ty][tz] = 1; dfs(tx, ty, tz); } } } int main() { freopen("engineer.in", "r", stdin); freopen("engineer.out", "w", stdout); cin >> l >> w >> h; cin >> m; for (int i = 1; i <= l; i++) for (int j = 1; j <= w; j++) for (int k = 1; k <= h; k++) cin >> a[i][j][k]; for (int i = 1; i <= l; i++) for (int j = 1; j <= w; j++) for (int k = 1; k <= h; k++) { if (!vis[i][j][k])//就是这里 { ans++; vis[i][j][k] = 1; dfs(i, j, k); } } cout << ans << endl; return 0; }

C.股票问题

反悔贪心模板题目

#include <bits/stdc++.h> using namespace std; int n; priority_queue<int, vector<int>, greater<int>> q; int main() { freopen("b.in", "r", stdin); freopen("b.out", "w", stdout); long long ans = 0; cin >> n; for (int i = 1; i <= n; i++) { int k; cin >> k; if (!q.empty() && q.top() < k)////如果今天的卖出股票比之前的某一天卖出股票更优的话,就买回之前的股票,然后再卖出今天的股票 ans += k - q.top(), q.pop(), q.push(k); q.push(k); } cout << ans << endl; return 0; }

D.灯泡开关

考虑加上一个等差数列。

怎么维护呢?先差分这个数组,举个例子,如果要在0 0 0 0 0 0 0 0 0 0 0中的3-7加一个从1开始的等差数列,

0 0 1 2 3 4 5 0 0 0 0差分后变成0 0 1 1 1 1 1 -5 0 0 0,就是一个区间+1后在末尾减掉最后一个数,

再差分一次,0 0 1 1 1 1 1 -5 0 0 0就变成了0 0 1 0 0 0 0 -6 5 0 0,发现等差数列差分两次后的数组只涉及三个数的修改。

所以我们每次更新原来的答案数组的差分再差分数组,最后前缀和还原差分数组以及还原原数组即可。

#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e6 + 10; int n, m; ll a[N]; ll cnt[N][2];//cnt[i]表示以i为舒适值最多少走多少 //0,1分别是因为这是一个环差分。 ll check() { ll res = 0; for (int i = 2; i <= n; i++) { if (a[i] > a[i - 1]) res += a[i] - a[i - 1]; else res += a[i] + m - a[i - 1]; } return res; } void change(int l, int r, int s) { // cout << l << ' ' << r << ' ' << s << endl; cnt[l][0] += s; cnt[r + 1][0] -= s; cnt[l + 1][1] += 1; cnt[r + 1][1] -= (r - l + 1); cnt[r + 2][1] += (r - l); } int main() { freopen("light.in", "r", stdin); freopen("light.out", "w", stdout); cin >> n >> m; for (int i = 1; i <= n; i++) cin >> a[i]; for (int i = 2; i <= n; i++) { if (a[i] > a[i - 1]) { if (a[i] - a[i - 1] >= 2) change(a[i - 1] + 2, a[i], 1); } else { if (m - a[i - 1] >= 2) change(a[i - 1] + 2, m, 1), change(1, a[i], m - a[i - 1]); if (m - a[i - 1] == 1) change(1, a[i], 1); if (m == a[i - 1]) { if (a[i] >= 2) change(2, a[i], 1); } } } for (int i = 2; i <= m + 1; i++) cnt[i][0] += cnt[i - 1][0], cnt[i][1] += cnt[i - 1][1]; for (int i = 2; i <= m + 1; i++) cnt[i][1] += cnt[i - 1][1]; ll ans = 0; for (int i = 1; i <= m; i++) ans = max(ans, cnt[i][0] + cnt[i][1]); cout << check() - ans << endl; return 0; }

__EOF__

本文作者ljfyyds
本文链接https://www.cnblogs.com/ljfyyds/p/17840972.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   ljfyyds  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示