[2019HDU多校第五场][HDU 6626][C. geometric problem]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6626
题目大意:给出平面上六个点\(A,B,M,N,X,Y\)以及两条直线\(L1,L2\),要求在四边形\(ABNM\)内,直线\(L1\)上选一点\(S\),在四边形\(XYNM\)内,直线\(L2\)上选一点\(T\),使得\(S_{ASB}=S_{SMTN}=S_{XYT}\)

题解:设\(L1\)交\(ABNM\)于点\(P,Q\),不妨设\(S=P+t\cdot (Q-P), 0\leq t \leq 1\),则有$$2S_{ASB}=\vec{AB}\times \vec{AS}=\vec{AB}\times (\vec{AP}+t\cdot \vec{PQ})=\vec{AB}\times \vec{AP}+t\cdot \vec{AB}\times \vec{PQ}$$
这个式子可以转换成为\(A+t\cdot B\)的形式。同理,三角形\(SMN,MNT,XYT\)均可以表示成这种形式,且\(ASB,SMN\)对应的\(t\)是\(S\)的坐标,不妨设为\(x\),另外两个三角形对应的\(t\)则设为\(y\)。这样我们就能得到$$\left\{\begin{matrix}
2S_{ASB}=\vec{AB}\times \vec{AP}+x\cdot \vec{AB}\times \vec{PQ}\\
2S_{SMN}=\vec{MN}\times \vec{MP}+x\cdot \vec{MN}\times \vec{PQ}\\
2S_{MNT}=\vec{MN}\times \vec{MP'}+y\cdot \vec{MN}\times \vec{P'Q'}\\
2S_{XYT}=\vec{XY}\times \vec{XP'}+y\cdot \vec{XY}\times \vec{P'Q'}
\end{matrix}\right.$$
根据题目要求,我们就能得出$$\left\{\begin{matrix}
2S_{ASB}-2S_{XYT}=\vec{AB}\times \vec{AP}-\vec{XY}\times \vec{XP'}+x\cdot \vec{AB}\times \vec{PQ}-y\cdot \vec{XY}\times \vec{P'Q'}=0\\
2S_{ASB}-2S_{SMN}-2S_{MNT}=\vec{AB}\times \vec{AP}-\vec{MN}\times \vec{MP}-\vec{MN}\times \vec{MP'}+x\cdot(\vec{AB}\times \vec{PQ}-\vec{MN}\times \vec{PQ})-y\cdot \vec{MN}\times \vec{P'Q'}=0
\end{matrix}\right.$$
这是一个二元一次方程组,当然我们也可以将其当成两条直线的标准式来看,求出他们的交点就能得出对应的答案了。
这里要注意,这里求出来的表达式可能不会有对应的直线(比如\(0\cdot x+0\cdot y=c \neq 0\)),或者会出现两直线没有交点,重合等情况,需要进行特判。另外还需要注意\(x,y\)解出来的值必须在\([0,1]\)这个范围内,否则也是无解。
另外,由于这题要求在多解时输出字典序最小的解,所以在我们求交点的时候就可以让点\(P\)的字典序比\(Q\)小,这样只要尽量让\(x,y\)取到最小值就好了
由于为了防止爆精度,看到坐标范围较小,想练习手写分数运算等种种原因,这题我除了输出外都是纯整数运算,不用担心爆精度了以后感觉改代码都方便了许多(指不需要调\(eps\)←_←)
#include<bits/stdc++.h>
using namespace std;
struct Frac
{
long long p,q;
void read(){q=,scanf("%lld",&p);}
void simp()
{int d=abs(__gcd(p,q));
p/=d,q/=d;
if(q<)p*=-,q*=-;
if(p==)q=abs(q);
}
Frac operator +(const Frac &t)const
{
Frac res={p*t.q+t.p*q,q*t.q};
res.simp();return res;
}
Frac operator -(const Frac &t)const
{
Frac res={p*t.q-t.p*q,q*t.q};
res.simp();return res;
}
Frac operator *(const Frac &t)const
{
Frac res={p*t.p,q*t.q};
res.simp();return res;
}
Frac operator /(const Frac &t)const
{
Frac res={p*t.q,q*t.p};
res.simp();return res;
}
bool operator <(const Frac &t)const
{
return p*t.q<q*t.p;
}
bool operator ==(const Frac &t)const
{
return p==t.p && q==t.q;
}
void print(){printf("%.12f",1.0*p/q);}
};
int sgn(Frac k)
{
if(k.p>)return ;
if(k.p<)return -;
return ;
}
struct Point
{
Frac x,y;
void read(){x.read(),y.read();}
Point operator +(const Point &t)const{return {x+t.x,y+t.y};}
Point operator -(const Point &t)const{return {x-t.x,y-t.y};}
Frac operator *(const Point &t)const{return x*t.y-y*t.x;}
Point operator *(const Frac &t)const{return {x*t,y*t};}
Point operator /(const Frac &t)const{return {x/t,y/t};}
bool operator <(const Point &t)const{return x==t.x?y<t.y:x<t.x;}
bool operator ==(const Point &t)const{return x==t.x && y==t.y;}
void print(){x.print(),putchar(' '),y.print();}
bool check()
{
if(sgn(x)< || sgn(y)<)return false;
if((Frac){,}<x || (Frac){,}<y)return false;
return true;
}
}A,B,M,N,X,Y,f[],g[],ans[];
struct Line
{
Point p1,p2;
void read(){p1.read(),p2.read();}
bool check_isct(const Point &A,const Point &B)const
{return sgn((p2-p1)*(A-p1))*sgn((p2-p1)*(B-p1))<=;}
Point isct_Point(const Line &t)const
{
Frac a=(p2-p1)*(t.p1-p1);
Frac b=(p2-p1)*(p1-t.p2);
return (t.p1*b+t.p2*a)/(a+b);
}
}L1,L2;
struct Line_Standard
{
Frac A,B,C;
bool check(){return sgn(A) || sgn(B) || !sgn(C);}
bool check_isct(const Line_Standard &t)const
{
Frac tmp=A*t.B-B*t.A;
if(sgn(tmp))return true;
return sgn(C*t.B-B*t.C)==;
}
Point isct_Point(const Line_Standard &t)const
{
Frac tmp=A*t.B-B*t.A;
if(!sgn(tmp))
{
if(sgn(C)==)return {{,},{,}};
if(sgn(B)==)return {{,},{,}};
if(sgn(A)==)return {{,},{,}};
}
return {(B*t.C-C*t.B)/tmp,(C*t.A-A*t.C)/tmp};
}
void print()
{
A.print(),putchar(' ');
B.print(),putchar(' ');
C.print(),putchar('\n');
}
}h1,h2;
int T,cnt;
void rua(const Line &L,const Point &A,const Point &B,const int &lim)
{
if(L.check_isct(A,B) && sgn((L.p2-L.p1)*(A-B)) && cnt<lim)
if(!(L.isct_Point({A,B})==f[cnt]) || cnt==lim-)
f[++cnt]=L.isct_Point({A,B});
}
void cal(const Point &A,const Point &B,const Point &C,const Point &D)
{
Frac st=(B-A)*(C-A);
Frac delta=(B-A)*(D-C);
Frac ed=(B-A)*(D-A);
if(sgn(st)< || sgn(ed)<)
st.p=-st.p,delta.p=-delta.p;
g[++cnt]={st,delta};
}
void print(const Point &P)
{
Point S=f[]+(f[]-f[])*P.x;
Point T=f[]+(f[]-f[])*P.y;
S.print(),putchar(' ');
T.print(),putchar('\n');
}
void init()
{
cnt=;
A.read(),B.read();
M.read(),N.read();
X.read(),Y.read();
L1.read(),L2.read();
rua(L1,A,B,),rua(L1,B,N,);
rua(L1,N,M,),rua(L1,M,A,);
rua(L2,X,Y,),rua(L2,Y,N,);
rua(L2,N,M,),rua(L2,M,X,);
if(f[]<f[])swap(f[],f[]);
if(f[]<f[])swap(f[],f[]);
cnt=;
cal(A,B,f[],f[]);
cal(M,N,f[],f[]);
cal(M,N,f[],f[]);
cal(X,Y,f[],f[]);
h1={g[].y,(Frac){,}-g[].y,g[].x-g[].x};
h2={g[].y-g[].y,(Frac){,}-g[].y,g[].x-g[].x-g[].x};
if(!h1.check() || !h2.check())
{printf("-1\n");return;}
cnt=;
Frac tmp=h1.A*h2.B-h1.B*h2.A;
if(sgn(tmp)==)
{
if(sgn(h1.C*h2.B-h1.B*h2.C))
{printf("-1\n");return;}
if(!sgn(h1.A) && !sgn(h1.B))
swap(h1,h2);
if(h1.check_isct({{,},{,},{,}}))
ans[++cnt]=h1.isct_Point({{,},{,},{,}});
if(h1.check_isct({{,},{,},{,}}))
ans[++cnt]=h1.isct_Point({{,},{,},{,}});
if(h1.check_isct({{,},{,},{-,}}))
ans[++cnt]=h1.isct_Point({{,},{,},{-,}});
if(h1.check_isct({{,},{,},{-,}}))
ans[++cnt]=h1.isct_Point({{,},{,},{-,}});
for(int i=;i<=cnt;i++)
if(ans[i].check())
{print(ans[i]);return;}
printf("-1\n");
return;
}
ans[++cnt]=h1.isct_Point(h2);
if(ans[].check())
{print(ans[]);return;}
printf("-1\n");
}
int main()
{
scanf("%d",&T);
while(T--)init();
}
[2019HDU多校第五场][HDU 6626][C. geometric problem]的更多相关文章
- [2019HDU多校第四场][HDU 6617][D. Enveloping Convex]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6617 题目大意:给出一凸包\(P\),求最小的与\(P\)相似且对应边平行的多边形,使得题目给出的\( ...
- [2019HDU多校第三场][HDU 6603][A. Azshara's deep sea]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6603 题目大意:给出一个凸包,凸包内有若干个圆,要求画尽可能多的对角线使得他们两两不在凸包内相交且不与 ...
- 2019HDU多校第五场A fraction —— 辗转相除法|类欧几里得
题目 设 $ab^{-1} = x(mod \ p)$,给出 $x,p$,要求最小的 $b$,其中 $0< a < b, \ 1 < x<p,\ 3 \leq x\leq {1 ...
- hdu 6088 Rikka with Rock-paper-scissors (2017 多校第五场 1004) 【组合数学 + 数论 + 模意义下的FFT】
题目链接 首先利用组合数学知识,枚举两人的总胜场数容易得到 这还不是卷积的形式,直接搞的话复杂度大概是O(n^2)的,肯定会TLE.但似乎和卷积有点像?想半天没想出来..多谢Q巨提醒,才知道可以用下面 ...
- hdu多校第五场1005 (hdu6628) permutation 1 排列/康托展开/暴力
题意: 定义一个排列的差分为后一项减前一项之差构成的数列,求对于n个数的排列,差分的字典序第k小的那个,n<=20,k<=1e4. 题解: 暴力打表找一遍规律,会发现,对于n个数的排列,如 ...
- 2014多校第五场1010 || HDU 4920 Matrix multiplication(矩阵乘法优化)
题目链接 题意 : 给你两个n*n的矩阵,然后两个相乘得出结果是多少. 思路 :一开始因为知道会超时所以没敢用最普通的方法做,所以一直在想要怎么处理,没想到鹏哥告诉我们后台数据是随机跑的,所以极端数据 ...
- 2014多校第五场1001 || HDU 4911 Inversion (归并求逆序数)
题目链接 题意 : 给你一个数列,可以随意交换两相邻元素,交换次数不超过k次,让你找出i < j 且ai > aj的(i,j)的对数最小是多少对. 思路 : 一开始想的很多,各种都想了,后 ...
- 2014 HDU多校弟五场J题 【矩阵乘积】
题意很简单,就是两个大矩阵相乘,然后求乘积. 用 Strassen算法 的话,当N的规模达到100左右就会StackOverFlow了 况且输入的数据范围可达到800,如果变量还不用全局变量的话连内存 ...
- 2014 HDU多校弟五场A题 【归并排序求逆序对】
这题是2Y,第一次WA贡献给了没有long long 的答案QAQ 题意不难理解,解题方法不难. 先用归并排序求出原串中逆序对的个数然后拿来减去k即可,如果答案小于0,则取0 学习了归并排序求逆序对的 ...
随机推荐
- vbox配置共享磁盘
本人实在配置Oracle rac的时候,进行共享磁盘的配置 以下操作要在虚拟机关机的情况下进行: 接下来按照步骤走即可
- Python_OpenCV视频截取并保存
在图像处理之前,我们需要对拿到手的数据进行筛选,对于视频,我们需要从中截取我们需要的一段或几段 整体思路比较简单,通过设定截取视频的起止时间(帧数),可以将该时间段内的图像保存为新的视频 直接上代码: ...
- GBK字符集
GBK字库 编辑 同义词 GBK一般指GBK字库 GBK全称<汉字内码扩展规范>(GBK即“国标”.“扩展”汉语拼音的第一个字母,英文名称:Chinese Internal Code Sp ...
- python第四天---元组和字典的魔法
# 元组,元素不可以更改.增加.删除 # 元组的第一级元素不可修改.删除.增加 # 一般写元组是,最后加上逗号 tu = (123, "wdsd", 213, (213, 213) ...
- Angular系列-AngularJs1使用Ace编辑器
Ace编辑器 Ace编辑器是一个嵌入web的代码编辑器,支持语法高亮,自动补全等功能,如果想在页面展示或编辑代码,使用该工具是很合适的. 参考项目地址:https://github.com/ajaxo ...
- Yet Another Problem On a Subsequence CodeForces - 1000D (组合计数)
大意:定义一个长为$k>1$且首项为$k-1$的区间为好区间. 定义一个能划分为若干个好区间的序列为好序列. 给定序列$a$, 求有多少个子序列为好序列. 刚开始一直没想出来怎么避免重复计数, ...
- 牛客 82E 无向图中的最短距离 (bitset,bfs)
有一个n个点的无向图,有m次查询,每次查询给出一些(xi,yi) 令dist(x,y)表示x和y点在图中最短距离,dist(x,x)=0,如果x,y不连通则dist(x,y) = inf 每次查询图中 ...
- Merkle树
在分布式系统.P2P应用中或者是区块链中,会经常使用一种数据结构Merkle tree(默克尔树),这里我们将详细讨论一下这个常用数据结构. Merkle tree Merkle树看起来非常像二叉树, ...
- (四)Maven中的仓库
一.分类 maven的仓库只有两大类: 1.本地仓库 2.远程仓库,在远程仓库中又分成了3种: 2.1 中央仓库 2.2 私服 2.3 其它公共库 二.本地仓库 本地仓库,顾名思义,就是Maven在本 ...
- C#操作DOS命令,并获取处理返回值
// /*---------------- // // 文件名:Method // // 文件功能描述: // // 使用 ADB 来进行安卓设备与PC端之间的文件交互,具体adb命令操作请百度 ...