CF1468F


题意:

给你 \(n\) 个以 \((x,y)\) 为开始,过点 \((u,v)\) 的射线,现在这些射线开始顺时针旋转,问有多少对射线可以同时互相过对方的 \((x,y)\)

思路:

首先思考什么时候会出现题目中这种情况,把射线所在直线画出发现如果两个直线不平行则始终存在一个夹角,那么只有两条射线所在直线平行时才行,但是射线方向相同时显然不行;

那么满足题意的射线必须满足:

  • 所在直线平行 \((k_1=k_2)\)
  • 方向相反

存斜率,判断方向就是把所有 \((x,y)\) 移动到原点然后判断 \((u,v)\) 所在象限即可

但是实测直接存斜率会挂精度,所以对斜率双哈希一下就行

代码:

#include
#define int long long
using namespace std;
int n;
struct node
{
	int x,y,u,v,op,k1,k2;
}a[(int)(1e5)+10];
map,int>m;
signed main()
{
	int t;cin>>t;
	while(t--)
	{
		m.clear();
		cin>>n;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i].x>>a[i].y>>a[i].u>>a[i].v;
			a[i].u-=a[i].x;
			a[i].v-=a[i].y;
			a[i].x=a[i].y=0;
		}
		for(int i=1;i<=n;i++)
		{
			if(a[i].v==0)
			{
				if(a[i].u>0)
				{
					a[i].k1=99224992999;
					a[i].k2=1919810;
					a[i].op=-3;
				}
				if(a[i].u<0)
				{
					a[i].k1=99224992999;
					a[i].k2=1919810;
					a[i].op=3;
				}
				m[make_pair(a[i].k1+a[i].k2,a[i].op)]++;
				continue;
			}
			if(a[i].u==0)
			{
				if(a[i].v>0)
				{
					a[i].k1=1149850917;
					a[i].k2=114514;
					a[i].op=-4;
				}
				if(a[i].v<0)
				{
					a[i].k1=1149850917;
					a[i].k2=114514;
					a[i].op=4;
				}
				m[make_pair(a[i].k1+a[i].k2,a[i].op)]++;
				continue;
			}
			a[i].k1=(int)(998244353*(double)((double)a[i].v/(double)a[i].u))%(1000000000007);
			a[i].k2=(int)((int)(2147483647)*(double)((double)a[i].v/(double)a[i].u))%(998244353);
			if(a[i].u>0&&a[i].v>0)
			{
				a[i].op=-1;
			}
			if(a[i].u<0&&a[i].v>0)
			{
				a[i].op=-2;
			}
			if(a[i].u<0&&a[i].v<0)
			{
				a[i].op=1;
			}
			if(a[i].u>0&&a[i].v<0)
			{
				a[i].op=2;
			}
			m[make_pair(a[i].k1+a[i].k2,a[i].op)]++;
		}
		int ans=0;
//		for(int i=1;i<=n;i++)
//		{
//			cout<