【牛客练习赛46-A】华华教奕奕写几何【二分】

博客围绕给出红色部分面积求大圆最短直径的问题展开。先将问题转化到圆中,设出相关直径,通过移项得到等式。因要求大圆直径最小,考虑二分法求解,还可二分验证直径合法性,同时提到要注意pi精度,时间复杂度为O(log2(maxlen))。

题目大意:

题目链接:https://ac.nowcoder.com/acm/contest/894/A
在这里插入图片描述
给出红色部分面积,求大圆的最短直径(两小圆直径之和等于大圆直径)。


思路:

o r z   W Y C , X Y Y d a l a o orz\ WYC,XYY dalao orz WYC,XYYdalao反正我是没有看出开个根号就好了。
先把问题转化为圆中的问题。
在这里插入图片描述

此时红色部分面积就为 2 s 2s 2s了。而所有圆的直径不变。
设两个小圆的直径分别为 x , y x,y x,y,大圆的直径为 m m m,我们欲求
π x 2 + π y 2 = π m 2 − 2 s πx^2+πy^2=πm^2-2s πx2+πy2=πm22s
移项得
2 s = π m 2 − π x 2 − π y 2 2s=πm^2-πx^2-πy^2 2s=πm2πx2πy2

2 s = π ( m 2 − x 2 − y 2 ) 2s=π(m^2-x^2-y^2) 2s=π(m2x2y2)

2 s π = m 2 − x 2 − y 2 \frac{2s}{π}=m^2-x^2-y^2 π2s=m2x2y2

等号左边是已知的。由于要求大圆的直径最小,所以可以考虑二分 m m m
有一点很显然的是,当两小圆直径差 ∣ x − y ∣ |x-y| xy越大,两小圆面积之和 π x 2 + π y 2 πx^2+πy^2 πx2+πy2越大。
所以这也是满足单调性的。可以考虑二分 x x x来验证直径为 m m m时是否合法。
p i pi pi保留小数点后15位。一开始保留7位被卡精度了。。。
时间复杂度 O ( log ⁡ 2 ( m a x l e n ) ) O(\log^2(maxlen)) O(log2(maxlen))


代码:

#include <cstdio>
#include <cmath>
using namespace std;

const double pi=3.141592653589793;
const double minn=0.00001;
double s;

bool check(double x)
{
	double l=0.0,r=x,mid,sum;
	while (r-l>=minn)
	{
		mid=(l+r)/2.0;
		sum=mid*mid+(x-mid)*(x-mid)+s;
		if (sum>x*x) r=mid;
			else l=mid;
	}
	if (x/2.0-r<=minn) return 0;
	return 1;
}

int main()
{
	scanf("%lf",&s);
	s=s*2.0/pi;
	double l=0.0,r=2000000.0,mid;
	while (r-l>=minn)
	{
		mid=(l+r)/2.0;
		if (check(mid)) l=mid;
			else r=mid;
	}
	printf("%0.3lf",l);
	return 0;
}
牛客练习赛题目通常需要实际编程操作才能解答,但我会尽力提供指导。如果你想了解C语言解法,这里假设前三题分别是基础的数值计算或数据结构操作: 1. 如果是简单的算术题,比如求两数之和,你可以这样: ```c #include <stdio.h> int main() { int a, b; printf("请输入两个整数:"); scanf("%d %d", &a, &b); int sum = a + b; printf("它们的和是:%d\n", sum); return 0; } ``` 2. 对于查找或排序算法,如查找数组中的最大值,可以这样做: ```c #include <stdio.h> int find_max(int arr[], int n) { int max = arr[0]; for (int i = 1; i < n; i++) { if (arr[i] > max) { max = arr[i]; } } return max; } int main() { int array[] = {5, 8, 3, 9, 1}; int size = sizeof(array) / sizeof(array[0]); int max_value = find_max(array, size); printf("最大值是:%d\n", max_value); return 0; } ``` 3. 如果涉及字符串处理,比如比较两个字符串,可以这样实现: ```c #include <stdio.h> #include <string.h> int string_compare(const char *str1, const char *str2) { return strcmp(str1, str2); } int main() { char str1[] = "Hello"; char str2[] = "World"; int result = string_compare(str1, str2); if (result < 0) { printf("str1 %s str2\n", "is less than"); } else if (result > 0) { printf("str1 %s str2\n", "is greater than"); } else { printf("str1 %s str2\n", "equals"); } return 0; } ``` 请注意,这只是一个简化的例子,实际比赛中的题目可能会更复杂,你还需要考虑错误处理、输入验证等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值