bzoj3621:我想那还真是令人高兴啊(复数)

Author Avatar
Sakits 3月 22, 2018

题解

  用来存复数模板的题…此题涉及复数加减乘除等于…
  因为复数相乘是幅长相乘,幅角相加,这刚好符合题目中放缩+旋转的定义,于是我们只需要找到一个点PP和复数TT满足:

(AP)T=(AP)(BP)T=(BP)(CP)T=(CP)\begin{gathered} (A-P)T=(A'-P)\\ (B-P)T=(B'-P)\\ (C-P)T=(C'-P) \end{gathered}

  由一二式得:

T=(AB)/(AB)P=(ATA)/(T1)\begin{gathered} T=(A'-B')/(A-B)\\ P=(AT-A')/(T-1) \end{gathered}

  代入第三式检验即可。
  记录一下复数的除法,总是忘呜呜呜…

a+bic+di=(a+bi)(cdi)(c+di)(cdi)=acadi+bcibdi2c2d2i2=(ac+bd)+(bcad)ic2+d2\begin{aligned} \frac{a+bi}{c+di} &=\frac{(a+bi)(c-di)}{(c+di)(c-di)}\\ &=\frac{ac-adi+bci-bdi^2}{c^2-d^2i^2}\\ &=\frac{(ac+bd)+(bc-ad)i}{c^2+d^2}\\ \end{aligned}

  然后这题就没了

代码

#include<iostream> 
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath> 
#include<algorithm> 
using namespace std;
const int maxn=500010, inf=1e9;
const double eps=1e-6;
struct cpx{double r, i;cpx(double _r=0, double _i=0):r(_r), i(_i){};}p[7];
cpx operator + (cpx a, cpx b){return cpx(a.r+b.r, a.i+b.i);}
cpx operator - (cpx a, cpx b){return cpx(a.r-b.r, a.i-b.i);}
cpx operator * (cpx a, cpx b){return cpx(a.r*b.r-a.i*b.i, a.r*b.i+a.i*b.r);}
cpx operator / (cpx a, cpx b)
{
	double dmr=b.r*b.r+b.i*b.i;
	return cpx((a.r*b.r+a.i*b.i)/dmr, (a.i*b.r-a.r*b.i)/dmr);
}
bool operator == (cpx a, cpx b){return fabs(a.r-b.r)<eps && fabs(a.i-b.i)<eps;}
int T;
double x, y;
inline void calc(int x, int y, int z)
{
	cpx T=(p[x+3]-p[y+3])/(p[x]-p[y]);
	cpx P=(p[x]*T-p[x+3])/(T-1);
	if((p[z]-P)*T==p[z+3]-P) 
	{
		printf("%.6lf %.6lf\n", P.r, P.i);
		throw true;
	}
}
int main()
{
	scanf("%d", &T);
	while(T--)
	{
		for(int i=1;i<=6;i++)
		scanf("%lf%lf", &x, &y), p[i]=cpx(x, y);
		try
		{
			calc(1, 2, 3); calc(1, 3, 2);
			calc(2, 1, 3); calc(2, 3, 1);
			calc(3, 1, 2); calc(3, 2, 1);
		}catch(bool){};
	}
}