思路
思路很简单,就是有亿点点细节。
- k = 1 : k=1: k=1: 答案显然是无限多个
-
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,b∗dx 即可,但是要注意
- 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=1和dx=−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=1和dx=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;
}