传送门
坐标系上给定两个不相交的圆,求所有过一定点且与这两个圆都外切的圆。

反演变换

如果把以那个定点为原点进行反演变换,那么过定点的圆就变成了直线,不过定点的圆还是圆,问题就转化成了求那两个圆的公切线。求出所有公切线再反演回圆再判是否都是外切。

#include <bits/stdc++.h>
using namespace std;
#define prt(k) cerr<<#k" = "<<k<<endl
typedef long long LL;
const int inf = 0x3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
int cmp(double x)
{return x < -eps ? -1 : x > eps;
}
struct P
{double x, y, r;P() { x = 0, y = 0, r = 1; }P(double xx, double yy, double rr =  1){x = xx, y = yy, r = rr;}P getP(double a){return P(x + cos(a)*r, y + sin(a)*r);}void in() { scanf("%lf%lf%lf", &x, &y, &r); }P operator * (double k) { return P(x*k, y*k, r*k); }P operator / (double k) {assert(abs(k) > 1e-8);return P(x/k, y/k);}void out(){printf("%.10f %.10f %.10f\n", x, y, r);}
};
double pf(double x) { return x * x; }
P operator-(P a, P  b)
{return P(a.x - b.x, a.y - b.y);
}
P operator+(P a, P  b)
{return P(a.x + b.x, a.y + b.y);
}
double abs(P p) { return sqrt(pf(p.x) + pf(p.y)); }
double dis(P a, P b) { return abs(a - b); }
typedef P Circle ;
P a, b, o;
double dot(P a, P b) { return a.x*b.x + a.y*b.y; }
P cuizhu(P p, P s, P t) ///点到直线垂足
{double r = dot(t-s, p-s)/dot(t-s, t-s);return s + (t-s)*r;
}
const double r = 1;
/// 圆的反演(结果是一个圆),反演中心O为原点,反演满足OC * OC' = r*r  这里 r = 1
/// 圆不经过反演中心
Circle inv(Circle a)
{double d1  =  abs(a);double r1 = a.r;double r2 = r1 / (d1 * d1 - r1 * r1) * r * r;double d2 = (r1 * r2 + r * r) / d1;double x = a.x / d1 * d2;double y = a.y / d1 * d2;P p = a * (r2 / r1);p.r = r2;return P(x, y, r2);
}
Circle inv(P s, P t) /// 直线的反演,直线不经过反演中心
{P O(0,0);P p = cuizhu(O, s, t);double d = dis(O, p);p = p * (0.5 / d / d);p.r = dis(p, O);return p;
}
/// 圆的切线,返回切线条数,见白书 267 页
int getTan(Circle A, Circle B, P a[], P b[])
{int cnt = 0;if (A.r < B.r) { swap(A, B); swap(a, b); }double d2 = pf(dis(A, B));double rdiff = (A.r - B.r);double rsum = A.r + B.r;if (d2 < pf(rdiff)) return 0;double base = atan2(B.y - A.y, B.x - A.x);if (d2 == 0 && A.r == B.r)  return -1;if (d2 == pf(rdiff)) {a[cnt] = A.getP(base); b[cnt++] = B.getP(base);return cnt;}double ang = acos((A.r - B.r) / sqrt(d2));a[cnt] = A.getP(base+ang); b[cnt++] = B.getP(base + ang);a[cnt] = A.getP(base - ang); b[cnt++] = B.getP(base - ang);if (d2 == rsum * rsum) {a[cnt] = A.getP(base); b[cnt++] = B.getP(PI + base);}else if (d2 > rsum * rsum) {double ang = acos((A.r + B.r) / sqrt(d2));a[cnt] = A.getP(base + ang); b[cnt++] = B.getP(base + ang);a[cnt] = A.getP(base - ang); b[cnt++] = B.getP(base - ang);}return cnt;
}
bool XiangQie(P a, P b)
{return cmp(dis(a, b) - a.r - b.r) == 0;
}
bool in(Circle C, P p)
{return cmp(dis(C, p) - C.r) == 0;
}
Circle A, B;
bool check(Circle ans)
{return XiangQie(A, ans) && XiangQie(B, ans) && in(ans, o);
}
int main()
{int re; scanf("%d", &re);while (re--) {a.in(); b.in();A = a, B = b;scanf("%lf%lf", &o.x, &o.y);a.x -= o.x; a.y -= o.y;b.x -= o.x; b.y -= o.y;a = inv(a); b = inv(b);P p1[55], p2[55];int cnt = getTan(a, b, p1, p2);vector<Circle> v;for (int i=0;i<cnt;i++) {Circle ans = inv(p1[i], p2[i]);ans.x += o.x; ans.y += o.y;if (check(ans)) v.push_back(ans);}printf("%d\n", v.size());for (auto C : v) C.out();}
}

HDU 4773 Problem of Apollonius 圆的反演相关推荐

  1. 【HDU 4773】Problem of Apollonius(圆的反演)

    传送门 定一个常数RRR和反演中心OOO 反演就是对于每一个点AAA变换到A′A'A′满足OA∗OA′=R2OA*OA'=R^2OA∗OA′=R2,其中A,A′,OA,A',OA,A′,O共线 对于反 ...

  2. 「HDU6158」 The Designer(圆的反演)

    题目链接多校8-1009 HDU - 6158 The Designer 题意 T(<=1200)组,如图在半径R1.R2相内切的圆的差集位置依次绘制1,2,3,到n号圆,求面积之和(n< ...

  3. 【科技】浅谈圆的反演

    一时兴起,就有了这篇博客.本人也学识浅薄,姑且讲一下我对于圆反演的一些皮毛之见. 首先我们要明白反演是什么: 反演是一种基本的几何变换.给定一个平面上的一个反演中心$O$和一个常数$k$,对于任意一个 ...

  4. HDU 6343.Problem L. Graph Theory Homework-数学 (2018 Multi-University Training Contest 4 1012)

    6343.Problem L. Graph Theory Homework 官方题解: 一篇写的很好的博客: HDU 6343 - Problem L. Graph Theory Homework - ...

  5. hdu 5687 Problem C 字典树

    传送门:hdu 5687 Problem C 中文题目就不做过多的解释 解题思路 定义一个结构体,里面有26个字母,就像下面这样: struct Node{int next[26];int sum;v ...

  6. HDU 6340 Problem I. Delightful Formulas(伯努利数 + 积性函数反演)

    Problem I. Delightful Formulas 大概就是照着题解抄了一遍吧,这道题太神仙了-- ai=ik,si=∑j=1iajcalc∑i=1nsi[gcd⁡(i,n)=1]∑d∣nμ ...

  7. bzoj2301: [HAOI2011]Problem b懵逼乌斯反演

    属于结果的和好求但是结果不好求的题 (轻易能得到以k的倍数为最大公约数的对数,但是不好直接求k) 所以一波反演结束 其实反演的时候完全没有反演的感觉,就是不停地恒等变形 算是懵逼乌斯反演最简单的例题 ...

  8. HDU 6428 Problem C. Calculate(积性函数)

    Problem C. Calculate ϕ=ϕ∗ϵ=ϕ∗μ∗Iϕ(n)=∑d∣n(ϕ∗μ)(d)设g(n)=∑d∣n(ϕ∗μ)(d)∑i=1A∑j=1B∑k=1Cϕ(gcd(i,j2,k3))∑i= ...

  9. [HDU](6333)Problem B. Harvest of Apples ---- 数论+莫队算法

    Problem Description There are n apples on a tree, numbered from 1 to n. Count the number of ways to ...

最新文章

  1. Uber做出艰难决定:关掉AI实验室,彭博社:Uber没有梦想
  2. map:根据 value 找 key ?
  3. java: jmap 查看内存信息
  4. 帅呆了!微软即将发布 Visual Studio for Mac 预览版
  5. BI-SqlServer
  6. 前端学习(1905)vue之电商管理系统电商系统之根据用户id查询对应的信息
  7. linux如何拷贝iphone文件夹,IPhone 手机如何和 Deepin 系统共享文件
  8. SpringCloud工作笔记084---SpringCloud项目中,关于防止表单提交_使用redis+Aspect面向切面实现
  9. 基于Modbus TCP的MCGS上位机软件教程
  10. web前端入门到实战:HTML图像标签img和源属性src及Alt属性、宽高、对齐
  11. 设计模式(三) 抽象工厂模式
  12. 小学生数据分析《西游记》发现大BUG
  13. linux下设置双系统选项,linux双系统【操作步骤】
  14. Mac网络正常但是所有浏览器无法上网问题解决
  15. 对比python字符串函数,学习pandas的str矢量化字符串函数
  16. 电脑录屏怎么把声音录进去,两招教你把声音录进去
  17. 汽车零部件行业SRM供应商协同系统:提升汽车零部件企业采购质量,驱动供应商快速响应
  18. 使用marven的方法
  19. ERP管理软件中“集成”的七个管理思想[转]
  20. 视频教程-Android WebRTC 实现1V1实时音视频通信-Android

热门文章

  1. 更改计算机oem信息软件,计算机属性信息修改方法(OEM信息修改方法)
  2. UML组件视图-组件图详解
  3. PDD 7.28秋招笔试题
  4. SMC 压缩空气速度调节阀air speed
  5. 【心情】今天看了日全食。。。
  6. 你需要多大的运算放大器带宽呢?
  7. 【秒懂音视频开发】06_重识声音
  8. 码分复用CDMA的原理
  9. VC6.0 C++编程错误error LNK2001
  10. Android开发 自定义ViewGroup 实现微信九格图功能(图片不同排布不同) 和 一种图片点击变暗效果