haut2023新生周赛题解

先说明一下,对于有些题测试样例不够强,导致一些非正解通过题目感到非常抱歉,收到反馈题目比较抽象.

A 旅行者的抛弃 签到题

根据重量比求出半径比 要注意重量比 是 M + 1

m1是可莉的重量,m2是要求的结果

m1 g1 / 2 = m2 g2

根据万有引力公式 : g = GM / (r * r)

得出 g1 / g2 的值

最后带入 可得 m2

最后直接输出


#include <bits/stdc++.h>
using namespace std;
void solve()
{
    double m, M;
    cin >> m >> M;
    double r = pow(M + 1, 1.0 / 3);
    cout << fixed << setprecision(3) << r * r / (M + 1) * m / 2;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int test = 1;
    // cin >> test;
    while (test--)
    {
        solve();
    }
    return 0;
}

B 元素中和之力 简单题

观察发现草或风只有一种中和反应方法,所以从草或风开始依次计算即可 反应时取反应元素中较小的元素值



#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve()
{
    ll x[8] = {0};
    int t;
    cin >> t;
    while (t--)
    {
        for (int i = 1; i <= 7; ++i)
        {
            cin >> x[i];
        }
        ll ans = 0;
        swap(x[4], x[7]); // 交换
        for (int i = 7; i >= 1; --i)
        {
            ll mi = min(x[i], x[i - 1]);
            if (mi > 0)
            {
                ans += mi;
                x[i - 1] -= mi;
            }
        }
        cout << ans  << "\n";
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int test = 1;
    // cin >> test;
    while (test--)
    {
        solve();
    }
    return 0;
}

C 旅行传送门 简单题

因为不会回头,考虑枚举中间点,在两边使用传送门,使用两个大空间数组,记录数字出现的位置,每枚举一次中间点都要将本次标记清除。

#include <bits/stdc++.h>
using namespace std;
const int N = 4e6 + 10;
typedef long long ll;
ll ma1[N], ma2[N];
ll a[N];
void solve() {
    int n;
    cin>> n;
    for(int i = 1; i <= n; ++i)cin>>a[i];
    ll ans = 0;
    for(int i = 1; i <= n; ++i){
        ll l = 0, r = 0;
        for(int j = i; j >= 1; --j){
            if(ma1[a[j]]==0){
                ma1[a[j]] = j;
            }
            else l = max(l, ma1[a[j]] - j);
        }
        for(int j = i + 1; j <= n; ++j){
            if(ma2[a[j]]==0){
                ma2[a[j]] = j;
            }
            else r = max(r, j - ma2[a[j]]);
        }
        // 清空数组
        for(int j = i; j >= 1; --j){
            ma1[a[j]] = 0;
        }
        for(int j = i + 1; j <= n; ++j){
            ma2[a[j]] = 0;
        }
        ans = max(ans, l + r);
    }
    cout<< ans;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int test = 1;
    while (test--) {
        solve();
    }
    return 0;
}

D 卡萨的阻拦 中等题

直接计算约数的耗时较大,应该会超时,考虑到一个比较小的数会是多个数的约数,所以直接计算这个数会被计算多少次 。对于输入的n, 对于某个 i , i <= n, 一共有 n / i 个数 有 i 这个 约数, 其中包括 i 本身 所以要减去 1, 所以单个 i 的贡献为 i * (n / i - 1), 循环求和即可 。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve()
{
    int n;
    cin>>n;
    ll ans = 0;
    for(int i = 1; i <= n; ++i){
        ans = ans + i * (n / i - 1);
    }
    cout<<ans;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int test = 1;
    // cin >> test;
    while (test--)
    {
        solve();
    }
    return 0;
}

E 破碎的未来 中等题

对于地图上的每一个点都对其进行标记, 如果四个方向中有一个点和其颜色相同,并且未被标记,将递归进行标记。

#include <bits/stdc++.h>
using namespace std;
int a[1100][1100];
int n,m;
void dfs(int i,int j,int op){
    if(i < 1 ||i > n || j < 1 || j > m )return;
    if(a[i][j] == -1)return;
    if(a[i][j] != op)return;
    a[i][j] = -1;
    dfs(i + 1,j, op);
    dfs(i -1, j, op);
    dfs(i, j + 1,op);
    dfs(i,j - 1, op);
}
void solve()
{
    cin>>n>>m;
    for(int i = 1; i <= n; ++i){
        for(int j = 1; j <= m; ++j){
            cin>>a[i][j];
        }
    }
    int ans = 0;
    for(int i = 1; i <= n; ++i){
        for(int j = 1; j <= m; ++j){
            if(a[i][j] != -1){
                dfs(i, j, a[i][j]);
                ans++;
            }
        }
    }
    cout<<ans;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int test = 1;
    // cin >> test;
    while (test--)
    {
        solve();
    }
    return 0;
}

F 怎么了,你累啦? 难题

提前记录对于位置 i 的后面和前面的最大值,如果位置 i 的值比这两个最大值都要小,那么这个值就一定会消失。 也可以用一个队列解决本问题,要注意判别条件

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve()
{
    int n;
    cin>>n;
    vector<ll> a(n + 10); // 数组
    vector<ll> r(n + 10); // 数组 // 记录后缀最大值
    r[n + 1] = 0;
    a[0] = 0;
    ll ma = 0; // 记录前缀最大值
    ll ans = 0;
    for(int i = 1; i <= n; ++i){
        cin>>a[i];
    }
    for(int i = n; i >= 1; --i){
        r[i] = max(r[i + 1], a[i]);
    }
    for(int i = 1; i <= n; ++i){
        ma = max(ma, a[i - 1]);
        if(a[i] >= ma || a[i] >= r[i + 1]){
            ans = ans + a[i];
        }
    }
    cout<< ans;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int test = 1;
    // cin >> test;
    while (test--)
    {
        solve();
    }
    return 0;
}

G 是心碎的声音 中等题

首先如果 k <= 2,所有原石都不会消失,直接输出 其次 将 原石从小到大排序, 如果小的能拿,一定优先拿小的,这将使用一次机会,最后计数即可

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve()
{
	int n, k;
	cin >> n >> k;
	vector<int> a(n);
	for (int i = 0; i < n; ++i)
	{
		cin >> a[i];
	}
	if (k <= 2)
	{
		cout << n << "\n";
		return;
	}
	sort(a.begin(), a.end()); // 排序
	ll ans = 0;
	ll time = 0;
	for (int i = 0; i < n; ++i)
	{
		ll op = 0;
		while (1)
		{
			a[i] = (1.0 * a[i] / k + 0.5);
			op++;
			if (op >= time + 1)
				break;
			if (a[i] == 0)
				break;
		}
		if (op >= time + 1)
		{
			time++;
			ans++;
		}
	}
	cout << ans << "\n";
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int test = 1;
	// cin >> test;
	while (test--)
	{
		solve();
	}
	return 0;
}

H 你就是被上天选中的人 中等题

对于每次操作1 和 2, 使用额外数组记录改变的值,对与操作3,枚举 x 的约数,因为操作 3 次数 有限制,但要注意枚举到约数 j 时,另一个约数 x / j 也要计算。

#include <bits/stdc++.h>
using namespace std;
const int N = 4e6 + 10;
typedef long long ll;
ll a[N], add[N]; // add 是额外数组
int n, m;
void solve()
{
	ll ans = 0;
	cin >> n >> m;
	for (int i = 1; i <= n; ++i)
	{
		cin >> a[i];
	}
	for (int i = 1; i <= m; ++i)
	{
		string s;
		int x, y;
		cin >> s;
		if (s[0] == 'u')
		{
			cin >> x >> y;
			add[x] += y;
		}
		else if (s[0] == 'd')
		{
			cin >> x >> y;
			add[x] -= y;
		}
		else
		{
			cin >> x;
			ll ans = a[x];
			for (int i = 1; i * i <= x; ++i)
			{
				if (x % i == 0)
				{
					ans += add[i];
					if(i * i != x){
						ans += add[x / i];
					}
				}
			}
			cout << ans << "\n";
		}
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int test = 1;
	// cin >> test;
	while (test--)
	{
		solve();
	}
	return 0;
}

全部评论

相关推荐

头像
11-27 14:28
长沙理工大学
刷算法真的是提升代码能力最快的方法吗?&nbsp;刷算法真的是提升代码能力最快的方法吗?
牛牛不会牛泪:看你想提升什么,代码能力太宽泛了,是想提升算法能力还是工程能力? 工程能力做项目找实习,算法也分数据结构算法题和深度学习之类算法
点赞 评论 收藏
分享
喜欢吃蛋糕仰泳鲈鱼是我的神:字节可以找个hr 给你挂了,再放池子捞
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务