UNIQUE VISION Programming Contest 2022(AtCoder Beginner Contest 248)——E

题目传送门

思路

思路很简单,就是有亿点点细节。

  1. k = 1 : k=1: k=1: 答案显然是无限多个
  2. k ! = 1 : k!=1: k!=1: 我们把所有直线存下来,然后看每条直线上有多少个点就可以得出答案。但是问题就出在存直线的时候,我们不能直接计算 y = k x + b y=kx+b y=kx+b , 因为这样浮点数误差很大。所以需要另辟蹊径,我们对斜截式变个形:
    在这里插入图片描述
    这样对于每条直线,我们存下 d x , d y , b ∗ d x dx,dy,b*dx dx,dy,bdx 即可,但是要注意
  • d x , d y dx,dy dx,dy 存的时候应该除以它们的 g c d gcd gcd
  • 对于 d x = 0 , d y = ± 1 dx=0,dy=\pm1 dx=0,dy=±1, x 1 , y 1 , x 2 , y 2 x1,y1,x2,y2 x1,y1,x2,y2 相同的情况下是同一条直线
  • 对于 d x = ± 1 , d y = 0 dx=\pm1,dy=0 dx=±1,dy=0, x 1 , y 1 , x 2 , y 2 x1,y1,x2,y2 x1,y1,x2,y2 相同的情况下是同一条直线
  • 对于 d x = 1 , d y = 1 和 d x = − 1 , d y = − 1 dx=1,dy=1和dx=-1,dy=-1 dx=1,dy=1dx=1,dy=1, x 1 , y 1 , x 2 , y 2 x1,y1,x2,y2 x1,y1,x2,y2 相同的情况下是同一条直线
  • 对于 d x = − 1 , d y = 1 和 d x = 1 , d y = − 1 dx=-1,dy=1 和 dx=1,dy=-1 dx=1,dy=1dx=1,dy=1, x 1 , y 1 , x 2 , y 2 x1,y1,x2,y2 x1,y1,x2,y2 相同的情况下是同一条直线
    所以我们需要处理上述情况,避免出现重复直线。如果有负数,我们永远指定 d x dx dx 为正数, d y dy dy 为负数即可。
	if(dx<0 || (dx==0 && dy<0)) dx=-dx,dy=-dy;

AC代码

#include<bits/stdc++.h>
#define rep(i,x,y) for(int i=x; i<=y; ++i)
#define per(i,x,y) for(int i=x; i>=y; --i)
#define pushk push_back
#define popk pop_back
#define mem(a,b) memset(a,b,sizeof a)
#define ll long long
#define lp p<<1
#define rp p<<1|1
using namespace std;
const int N = 320;
ll x[N],y[N];
int cnt[N*N];
int main() {

	int n,k;
	cin>>n>>k;
	rep(i,1,n) {
		cin>>x[i]>>y[i];
	}
	if(k==1) puts("Infinity");
	else {
		int idx=1;
		set<array<ll,3>> se;
		rep(i,1,n) {
			rep(j,i+1,n) {
				ll dy= (y[i]-y[j]);
				ll  dx = (x[i]-x[j]);
				ll g=__gcd(abs(dx),abs(dy));
				dx/=g;
				dy/=g;
				if(dx<0 || (dx==0 && dy<0)) dx=-dx,dy=-dy;
				ll dxb=y[i]*dx-dy*x[i];
				se.insert({dx,dy,dxb});
			}
		}
		int ans=0;
		idx=0;
		for(auto &it : se) {
			idx++;
			rep(j,1,n) {
				if(x[j]*it[1]+it[2]==y[j]*it[0]) cnt[idx]++;
			}
		}
		rep(i,1,(int)se.size()) {
			if(cnt[i]>=k) {
				ans++;
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值