2011成都网赛 / 1003 - Regular Polygon

本文讨论了一个使用余弦定理构造特定函数并应用二分搜索法求解的问题。详细介绍了函数定义、边界设定错误及修正过程,并通过实例展示了如何通过二分法找到最优解。重点在于理解单调函数在求解过程中的作用。

题目

利用余弦定理,构造函数 b=sigma(acos(a[i]^2+a[i+1]^2-e^2)/(2a[i]a[i+1]))。e为边长。当e为解时,b=2*pi(内角和)。重点是,b(e)是单调上升的。所以可以二分。(事实上我觉得这种题目必然要二分,重点就是找一个单调函数)。

写的时候,犯了个很傻逼的错误,还以为是精度问题,就一直改精度........(我发现其实做eps的精度,就把eps对应成整数里的1来理解就是了,二分、比较大小什么的都是跟整数同理的,这样好想很多)。 改到我觉得精度不可能有问题的时候...........突然发现,原来我开始的上下界写错了。竟然把 +-eps写到循环里了.......还有,这题是maxe=min(a[i]+a[i+1]),mine=max(fabs(a[i]-a[i+1])) 的.......这里写的时候也傻逼了。


代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;

#define MAXN 110
#define INF 1<<30
#define pi acos(-1.0)
#define eps 1e-8											//eps !!
double a[MAXN];		//边长
int n;

double f(double x1, double x2, double e)	//返回角度
{
	return acos((x1*x1+x2*x2-e*e)/(2*x1*x2));
}

double func(double e)	//	f(边长)-> 2pi
{
	double ret=0;
	for(int i=0; i<n; i++)
	{
		int j=(i+1)%n;
		ret+=f(a[i], a[j], e);
	}
	return ret;
}

int cmp(double x, double y)
{
	if(fabs(x-y)<eps) return 0;						//
	else if(x>=y+eps) return 1;			//x>=y+eps
	else return -1;
}
double solve()
{
	double maxe=INF, mine=0;					//① 很容易错,因为max值是取min操作的........
	for(int i=0; i<n; i++)
	{
		int j=(i+1)%n;
//		maxe = max(maxe, a[i]+a[j])-eps;				//!!!!	傻逼
//		mine = min(mine, fabs(a[i]-a[j]))+eps;

		//maxe = max(maxe, a[i]+a[j]);					//!!!傻逼,too
		//mine = min(mine, fabs(a[i]-a[j]));
		maxe = min(maxe, a[i]+a[j]);	
		mine = max(mine, fabs(a[i]-a[j]));
	}
	double l=mine+eps, r=maxe-eps;

	int yes=0;		//防止一直处于 l=r
	while(r-l>eps || !cmp(r, l))	//相当于eps精度下的 l<=r
	{

		double mid=(l+r)/2;
		double t = func(mid);

//printf("t=%lf, 2*pi=%lf, sub=%.10lf\n", t, 2*pi, fabs(t-2*pi));
		int flag = cmp(t, 2*pi);
		if(!flag)	return mid;
		else if(flag>0) r=mid-eps;
		else if(flag<0) l=mid+eps;

//printf("(%.10lf, %.10lf), sub=%.10lf, eps=%.10lf\n", l, r, r-l, eps);

		if(yes) break;
		if(!cmp(l, r)) yes=1;
	}
	return 0;
}

int main()
{
	int t;	scanf("%d", &t);
	for(int T=0; T<t; T++)
	{
		printf("Case %d: ", T+1);

		scanf("%d", &n);
		for(int i=0; i<n; i++)
		{
			scanf("%lf", &a[i]);
		}

		double t = solve();
		if(t) printf("%.3lf\n", t);
		else printf("impossible\n");
	}
}



源码地址: https://pan.quark.cn/s/d1f41682e390 miyoubiAuto 米游社每日米游币自动化Python脚本(务必使用Python3) 8更新:更换cookie的获取地址 注意:禁止在B站、贴吧、或各大论坛大肆传播! 作者已退游,项目不维护了。 如果有能力的可以pr修复。 小引一波 推荐关注几个非常可爱有趣的女孩! 欢迎B站搜索: @嘉然今天吃什么 @向晚大魔王 @乃琳Queen @贝拉kira 第三方库 食用方法 下载源码 在Global.py中设置米游社Cookie 运行myb.py 本地第一次运行时会自动生产一个文件储存cookie,请勿删除 当前仅支持单个账号! 获取Cookie方法 浏览器无痕模式打开 http://user.mihoyo.com/ ,登录账号 按,打开,找到并点击 按刷新页面,按下图复制 Cookie: How to get mys cookie 当触发时,可尝试按关闭,然后再次刷新页面,最后复制 Cookie。 也可以使用另一种方法: 复制代码 浏览器无痕模式打开 http://user.mihoyo.com/ ,登录账号 按,打开,找到并点击 控制台粘贴代码并运行,获得类似的输出信息 部分即为所需复制的 Cookie,点击确定复制 部署方法--腾讯云函数版(推荐! ) 下载项目源码和压缩包 进入项目文件夹打开命令行执行以下命令 xxxxxxx为通过上面方式或取得米游社cookie 一定要用双引号包裹!! 例如: png 复制返回内容(包括括号) 例如: QQ截图20210505031552.png 登录腾讯云函数官 选择函数服务-新建-自定义创建 函数名称随意-地区随意-运行环境Python3....
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值