【HDU6158】The Designer(圆的反演)

传送门


题解:

这道题 n n n 很大,但是这不是问题,是个人都知道在面积足够小的时候直接break掉,所以问题在于怎么求出下一个圆。

直接求显然很麻烦,考虑反演,以两个大圆的切点为反演中心,两个大圆反演后显然就是两条直线,而那些小圆就是夹在直线中的一个个等圆,直接反演回去得到半径即可。


代码:

#include<bits/stdc++.h>
#define ll long long
#define re register
#define db double
#define cs const

using std::cerr;
using std::cout;

cs db eps=1e-14;
cs db PI=acos(-1);

db R,r1,r2;

int sign(db x){return x<-eps?-1:(x>eps?1:0);}

struct Pnt{
	db x,y;Pnt(){}Pnt(db _x,db _y):x(_x),y(_y){}
	friend Pnt operator-(cs Pnt &a,cs Pnt &b){return Pnt(a.x-b.x,a.y-b.y);}
	friend Pnt operator+(cs Pnt &a,cs Pnt &b){return Pnt(a.x+b.x,a.y+b.y);}
	friend Pnt operator*(cs Pnt &a,cs db b){return Pnt(a.x*b,a.y*b);}
	friend Pnt operator/(cs Pnt &a,cs db b){return Pnt(a.x/b,a.y/b);}
	inline db len()cs{return sqrt(x*x+y*y);}
};

inline db sqr(db x){return x*x;}
inline db dis(cs Pnt &a,cs Pnt &b){
	return (a-b).len();
}

inline db get_r(cs Pnt &o,cs db &r){
	return r/(sqr(o.len())-sqr(r))*sqr(R);
}

void Main(){
	R=20;int T;scanf("%d",&T);
	while(T--){
		scanf("%lf%lf",&r1,&r2);
		if(r1<r2)std::swap(r1,r2);
		db x1=sqr(R)/(2*r1);
		db x2=sqr(R)/(2*r2);
		db r=(x2-x1)/2;Pnt o((x1+x2)/2,0);
		db nowr=get_r(o,r);
		db ans=sqr(nowr);
		int n;scanf("%d",&n);
		for(int re i=2;i<=n;++i){
			if((i&1)==0)o.y+=2*r,nowr=get_r(o,r);
			ans+=sqr(nowr);if(sqr(nowr)*PI<eps)break;
		}printf("%.5f\n",ans*PI);
	}
}

void file(){
#ifdef zxyoi
	freopen("designer.in","r",stdin);
#endif
}
signed main(){file();Main();return 0;}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值