2020牛客寒假算法基础集训营5 部分题解(BDEH)

本文精选了算法竞赛中常见的几类题目,包括最小圆覆盖问题的二分搜索解法、贪心策略解决牛牛与牛妹的约会问题、博弈论在Enjoy the game问题中的应用,以及Hash函数在进制转换问题中的巧妙运用。通过具体实例,深入浅出地讲解了算法设计思路及代码实现。

B: 牛牛战队的比赛地(二分做法)
题意:二维平面给定n个点,在x轴找一点使得到n个点距离的最大值最小。

思路:
我们可以将问题转化为在x轴找到一个圆心,使得该圆包含这n个点且半径最小,这样就变成了最小圆覆盖问题。有关于最大值最小此类问题,我们第一个想到的就应该是二分了,关键在于二分半径后如何check呢?
首先我们需要明白这样一个前提,也是解题的关键点:一个半径为R的圆,我们任意在圆上或圆内找一个点,也做半径为R的圆,那么这个圆一定会包含之前那个圆的圆心。
明白了这个,问题就easy了,我们将二分得到的半径R,把n个点都拿来做这样半径为R的圆,与x轴相交的部分,说明圆心可能落在这一范围内,然后我们只要看这些区域是否产生矛盾就好了。比如点1与x轴相交范围为[3,6],点2为[7,10],没有相交的部分,显然答案矛盾,即不存在半径为R的圆可以包含全部点。

#include <bits/stdc++.h>
#define x first
#define y second
#define d double
using namespace std;
const int N = 2e5 + 5;
int n;
pair<d, d> p[N];

bool check(d o)
{
    d l, mi = -1e18, ma = 1e18;
    for (int i = 1; i <= n; i++)
    {
        if (o < fabs(p[i].y))
            return false;
        l = sqrt(o - p[i].y) * sqrt(o + p[i].y); ///等价于sqrt(o*o-p[i].y*p[i].y)
        mi = max(mi, p[i].x - l);
        ma = min(ma, p[i].x + l);
    }
    return mi <= ma; ///判断最大的左端点<=最小的右端点即可
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> p[i].x >> p[i].y;
    d l = 0, r = 1e18, mid;
    int t = 250;
    while (t--)
    {
        mid = (l + r) / 2.0;
        if (check(mid))
            r = mid;
        else
            l = mid;
    }
    cout << fixed << setprecision(6) << r;
    return 0;
}

D:牛牛与牛妹的约会 (贪心)
题解:我们先明确何时开根号走会更优,即:x - x^(1/3) > 1,解得x>2.3247179,因此我们贪心的按开根号走直到x<=2.3247179,同时维护最小值即可。

#include <bits/stdc++.h>
using namespace std;
double cal(double x)
{
	double l = 0, r = x, mid;
	int q = 50;
	while (q--)
	{
		mid = (l + r) * 0.5;
		if (mid * mid * mid >= x)
			r = mid;
		else
			l = mid;
	}
	return r;
}
int main()
{
	int t;
	while (~scanf("%d", &t))
	{
		while (t--)
		{
			double a, b;
			scanf("%lf%lf", &a, &b);
			double now = 0, ans = fabs(a - b);
			if (a >= 0)
			{
				while (a >= 2.3247179)
				{
					now += 1.0;
					a = cal(a);
					ans = min(ans, fabs(a - b) + now);
				}
			}
			else if (a < 0)
			{
				a = -a;
				b = -b;
				while (a >= 2.3247179)
				{
					now += 1.0;
					a = cal(a);
					ans = min(ans, fabs(a - b) + now);
				}
			}
			printf("%.9f\n", ans);
		}
	}
	return 0;
}

E: Enjoy the game (博弈)
题解:多写几个就看出来了,是二次幂后手胜,否则先手胜。

#include <bits/stdc++.h>
using namespace std;
int main()
{
	int n;
	cin >> n;
	if (!(n & (n - 1)))    ///判断是否为2次幂
		cout << "Alice";
	else
		cout << "Bob";
	return 0;
}

H:Hash (进制转化)
题解:
x%mod=p 不难得到 (x+mod)%mod=p
所以字符串加个mod就可以了,判一下长度是否还为6即可。

#include <bits/stdc++.h>
using namespace std;
char s[20], a[105];
int mod, k, x;
int main()
{
    while (~scanf("%s%d", s, &mod))
    {
        memset(a, 0, sizeof(a));
        k = x = 0;
        for (int i = 0; i < 6; i++)
            x = x * 26 + s[i] - 'a';  ///转为10进制
        x += mod;
        while (x)      ///转回26进制
        {
            a[++k] = x % 26;
            x /= 26;
        }
        if (k <= 6)
        {
            if (k < 6)  ///长度不够6补a即可
                k++;
            for (int i = k; i >= 1; i--)
                printf("%c", a[i] + 'a');
        }
        else
            printf("-1");
        puts("");
    }
    return 0;
}
「LLM那些事」系列第 4 篇《上下文窗口的边界》,文章连接:https://blog.csdn.net/houwenjin/article/details/163999753。 演示什么:在「预测」Sheet 的黄色格子里输入一句话(默认「来泡一杯」),四个「模型」——分别只统计最后 1 / 2 / 3 / 4 个字的 n-gram 查表——同时预测下一个字。同一个输入,看的上下文越长,候选越少、预测越确定: ┌────────────────┬──────────┬───────────────┬──────┐ │ 只看最后几个字 │ 用的前缀 │ 候选下一字数 │ 预测 │ ├────────────────┼──────────┼───────────────┼──────┤ │ 1 个 │ 杯 │ 3(茶/子/水) │ 模糊 │ ├────────────────┼──────────┼───────────────┼──────┤ │ 2 个 │ 一杯 │ 2(茶/水) │ 收窄 │ ├────────────────┼──────────┼───────────────┼──────┤ │ 3 个 │ 泡一杯 │ 1(茶) │ 确定 │ ├────────────────┼──────────┼───────────────┼──────┤ │ 4 个 │ 来泡一杯 │ 1(茶) │ 确定 │ └────────────────┴──────────┴───────────────┴──────┘
源码下载地址: https://pan.quark.cn/s/a4b39357ea24 笔记本的散热风扇管理 ---------------------------------------- 09 November 2006. 对于版本20061109的变更概述如下: 1) ACPI CA核心子系统:在源操作数是一个操作区域的场景下,对负载ASL操作符进行了优化。仅需映射操作区域内存,而不是执行逐字节读取。 (区域必须为SystemMemory类型,见下文。)修正了源操作数为区域字段的负载ASL操作符问题。也允许缓冲区对象作为源操作数。 BZ 480 解决了负载ASL操作符允许源操作数为任意类型操作区域的问题。现被限制为仅SystemMemory类型的区域,符合ACPI规范。 BZ 481 对新表管理器代码进行了额外的清理和优化。AcpiEnable将在所有必需的ACPI表未加载时失败(FADT, FACS, DSDT)。 BZ 477 在acobject.h中添加了#pragma pack(8/4),以确保此头文件中的结构始终编译为对齐。ACPI_OPERAND_OBJECT已被手动优化为对齐,并在字节打包时无法工作。示例代码和数据大小:这些是Microsoft Visual C++ 6.0 32位编译器生成的、与操作系统无关的acpica.lib的大小。调试版本的代码包含调试输出跟踪机制,具有更大的代码和数据大小。上一个版本:非调试版本:78.1K代码,17.1K数据,95.2K总计 调试版本:155.4K代码,63.1K数据,218.5K总计 当前版本:非调试版本:77.9K代码,17.0K数据,94.9K总计 调试版本:155.2K代码,63.1K数据,...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值