本题可以从直线一般式入手 Ax+By+C=0 , 即:
(y1-y2) * x +(x2-x1) * y +( x1 * y2 - x2 * y1)=0
考虑到A、B、C可能成倍数关系,但它们是一条直线,只记录一次,因此用__gcd(x,y)函数求出A、B、C三者的最大公因数并相除。
考虑到直线会有重复的情况,因此选用集合set储存A、B、C。set 是一个有序的容器,里面的元素都是排序好的,支持插入,删除,查找等操作,就像一个集合一样。set 插入的元素不能相同,且set 中的元素不像 map 那样可以同时拥有实值(value)和键值(key),只能存储键,是单纯的键的集合,因此用pair中套pair的形式{{A,B}C}来存储键值,最后返回集合大小即为直线数。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<set>
using namespace std;
typedef pair<int,int> PII;
typedef pair<PII,int> PIII;
vector<PII> v;
set<PIII> s;
int x,y;
int main(){
cin>>x>>y;
for(int i=0;i<x;i++){
for(int j=0;j<y;j++){
v.push_back({i,j});
}//for2
}//for1
int x1,y1,x2,y2,A,B,C,ggcd;
for(int i=0;i<v.size();i++){
for(int j=i+1;j<v.size();j++){
x1=v[i].first;
y1=v[i].second;
x2=v[j].first;
y2=v[j].second;
A=x1-x2;
B=y1-y2;
C=x2*y1-x1*y2;
ggcd=__gcd(__gcd(A,B),C);
A=A/ggcd, B=B/ggcd, C=C/ggcd;
s.insert({{A,B},C});
}//for2
}//for1
cout<<s.size()<<endl;
return 0;
} //main