好好打比赛每场都或多或少有些收获 ,昨天被牛客的C卡死,细节满满,今天早上又写了很久,收获还是蛮大的
辗转相除法求最大公约数
原理什么的就不说了,我之前的写法都是
ll gcd(ll x, ll y)
{
return (x % y == 0) ? y : gcd(y, x % y);
}
这种写法挺常见的,不过有一个弊端,就是如果y为0的时候会出现%0
的RE
稍微改一下:
ll gcd(ll x, ll y)
{
return (y == 0) ? x : (gcd(y, x % y));
}
这样的话如果y为0,会输出x
另外一点题外话:关于0和一个数a的最大公约数,我百度到有两种说法,一种说是数a,另一种说是不存在。
用上面的写法2默认最大公约数是数a,但是最主要的是规避的RE问题
存储斜率
斜率问题也是经常遇到的,不过我之前都是直接存成浮点,昨天才意识到最正确的方式应该是存成pair,毕竟之前也提到了浮点数是有精度问题的。(虽然现在还没被卡过,不过以后要注意了)
题目:传送门
题目大意不说了,直接说思路
比较简单的两种情况:
直接到达(0):需要到达的点就是原点
一次到达:需要到达的点与原点练成的直线经过一个存在的点
两次到达情况比较复杂,但是三次才能到达只有一种情况,就是之前只存在两个点,并且与要到达的点 形成平行四边形的时候,如下图:
证明略(不会)
AC代码:
浮点解法:
map<double, int> mp1;
struct node
{
double x, y;
} nd[100010];
ll ct = 1;
int main()
{
IOS;
double mod = 123412117;
ll n, q;
cin >> n >> q;
mp1.clear();
for (int i = 1; i <= n; i++)
{
double x, y;
cin >> x >> y;
if (x == 0 && y == 0)
{
n--;
i--;
continue;
}
if (x == 0)
{
if (!mp1[mod] && ct <= 3)
{
nd[ct].x = x;
nd[ct++].y = y;
}
mp1[mod]++;
}
else
{
if (!mp1[y / x] && ct <= 3)
{
nd[ct].x = x;
nd[ct++].y = y;
}
mp1[y / x]++;
}
}
while (q--)
{
double x1, y1;
cin >> x1 >> y1;
if (x1 == 0 && y1 == 0)
{
cout << 0 << endl;
continue;
}
double temp = (x1 == 0) ? mod : (y1 / x1);
if (mp1.count(temp))
{
cout << 1 << endl;
continue;
}
if (mp1.size() <= 1)
cout << -1 << endl;
else if (mp1.size() == 2)
{
if (n == 2)
{
double dis1n = (nd[1].x - x1) * (nd[1].x - x1) + (nd[1].y - y1) * (nd[1].y - y1);
double dis2n = (nd[2].x - x1) * (nd[2].x - x1) + (nd[2].y - y1) * (nd[2].y - y1);
double dis01 = (nd[1].x) * (nd[1].x) + (nd[1].y) * (nd[1].y);
double dis02 = (nd[2].x) * (nd[2].x) + (nd[2].y) * (nd[2].y);
if (dis1n == dis02 && dis2n == dis01)
cout << 3 << endl;
else
cout << 2 << endl;
}
else
cout << 2 << endl;
}
else
cout << 2 << endl;
}
return 0;
}
pair解法:
map<pair<ll, ll>, ll> mp;
ll gcd(ll x, ll y)
{
return (y == 0) ? x : (gcd(y, x % y));
}
ll xx[100010];
ll yy[100010];
ll ct = 1;
int main()
{
ll n, q, temp_gcd;
cin >> n >> q;
for (int i = 1; i <= n; i++)
{
ll x, y;
cin >> x >> y;
if (x == 0 && y == 0)
{
i--;
n--;
continue;
}
xx[ct] = x;
yy[ct++] = y;
temp_gcd = gcd(x, y);
mp[make_pair(x / temp_gcd, y / temp_gcd)] = 1;
}
while (q--)
{
ll x, y;
cin >> x >> y;
if (x == 0 && y == 0)
{
cout << 0 << endl;
continue;
}
temp_gcd = gcd(x, y);
if (mp.count(make_pair(x / temp_gcd, y / temp_gcd)))
{
cout << 1 << endl;
continue;
}
if (mp.size() <= 1)
{
cout << -1 << endl;
continue;
}
if (mp.size() > 2)
{
cout << 2 << endl;
continue;
}
if (n == 2)
{
if (xx[1] + xx[2] == x && yy[1] + yy[2] == y)
{
cout << 3 << endl;
continue;
}
cout << 2 << endl;
}
}
return 0;
}