提出 #31046558
ソースコード 拡げる
//https://atcoder.jp/contests/abc248/tasks/abc248_e
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<b;i++)
#define rrep(i,a,b) for(int i=a;i>=b;i--)
#define fore(i,a) for(auto &i:a)
#define all(x) (x).begin(),(x).end()
//#pragma GCC optimize ("-O3")
using namespace std; void _main(); int main() { cin.tie(0); ios::sync_with_stdio(false); _main(); }
typedef long long ll; const int inf = INT_MAX / 2; const ll infl = 1LL << 60;
template<class T>bool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T& a, const T& b) { if (b < a) { a = b; return 1; } return 0; }
//---------------------------------------------------------------------------------------------------
ll gcd(ll a, ll b) { return a ? gcd(b % a, a) : b; }
/*---------------------------------------------------------------------------------------------------
∧_∧
∧_∧ (´<_` ) Welcome to My Coding Space!
( ´_ゝ`) / ⌒i @hamayanhamayan
/ \ | |
/ / ̄ ̄ ̄ ̄/ |
__(__ニつ/ _/ .| .|____
\/____/ (u ⊃
---------------------------------------------------------------------------------------------------*/
pair<ll, ll> normalization(ll up, ll down, bool slope = true) {
if (down < 0) {
up *= -1;
down *= -1;
}
if (down == 0) {
if (slope) up = 1;
}
else {
ll g = gcd(abs(up), down);
up /= g;
down /= g;
}
return {up, down};
}
int N, K; ll X[301], Y[301];
tuple<ll, ll, ll, ll> getParameter(int a, int b) {
ll dx = X[a] - X[b];
ll dy = Y[a] - Y[b];
tie(dy, dx) = normalization(dy, dx);
// ya = dy * xa / dx + b
// b = (ya * dx - dy * xa) / dx
ll bup = Y[a] * dx - dy * X[a];
ll bdown = dx;
tie(bup, bdown) = normalization(bup, bdown, false);
return { dy, dx, bup, bdown };
}
void _main() {
cin >> N >> K;
rep(i, 0, N) cin >> X[i] >> Y[i];
if (K == 1) {
cout << "Infinity" << endl;
return;
}
map<tuple<ll, ll, ll, ll>, int> cnt;
rep(a, 0, N) rep(b, a + 1, N) cnt[getParameter(a, b)]++;
map<int, int> rcomb;
rep(n, K, N + 1) rcomb[n * (n - 1) / 2] = 1;
int ans = 0;
fore(p, cnt) ans += rcomb[p.second];
cout << ans << endl;
}
/* ///////////////////////// writeup1 start
///////////////////////// writeup2 start
幾何問題。
以下解法、非常に面倒なので、別の解法があるかも…
## (解法に移る前に)
以下のケースでちょっとはまったので、WAではまってる人はこれを確認してみるといいかも。
```
6 3
1 3
1 4
1 5
6 10
6 11
6 12
```
## Infinityのとき
K=1の場合はどのような場合でも無数に解が存在する。
K=1の時は、Infinityと出して終了しよう。
## どういった方針を取るか
今回は点を通る直線を題材とした問題であるが、直線は少なくとも2点があれば作成することができる。
逆に3点あると複数の直線ができてしまったり、色々面倒なので、2点を使った直線から解法が導けないか考えてみる。
ここから思考が飛ぶが、試行錯誤がこの間にあったと考えてほしい…
例えば、任意のa番目の点とb番目の点(a<b)について直線を列挙していったときに、
同一直線状に3点ある直線は3回現れる。点abcを通っていれば、ab,ac,bcの列挙時に出てくる。
同一直線状に4点ある直線は6回現れる。点abcdを通っていれば、ab,ac,ad,bc,bd,cdの列挙時に出てくる。
つまり、同一直線についてはn点あれば、C(n,2)回現れることになる。(関数Cは二項係数)
よって、
cnt[ (ある直線を表す何らかの情報)] := 任意の2頂点を選んだときにある直線が何通りあるか
というのが計算できれば、その個数から直線に何個点があるかを逆算することができる。
## 『ある直線を表す何らかの情報』
自分はこれに傾きと切片を使った。
入力値が[-10^9,10^9]だったので、doubleは落ちそうな気配があり、有理数でどちらも保持する道を選んだ。
傾きをdx/dy, 切片をbup/bdownという風に有理数で定義して、2つの分数について正規化をすれば、
(dx, dy, bup, bdown)の数の組がとある直線を一意に表してくれるようになる。
以下の関数を作って計算している。
getParameter(a,b) := 2頂点a,bを通る直線を表す(dx, dy, bup, bdown)を返す
具体的には
https://blog.hamayanhamayan.com/entry/2018/09/30/203639
っぽいことをやる。
> a = (ya - yb) / (xa - xb)
> b = (xa * yb - xb * ya) / (xa - xb)
という感じで分数を作って、ソースコードにあるnormalization関数みたいに有理化する感じである。
(xa - xb)が0になるときが注意で、傾きは分子を1にするが、切片は分子をそのままにしている。
縦の直線なので、傾きと切片を定義はできないのだが、便宜上このようにして直線を同一視させている。
///////////////////////// writeup2 end */
提出情報
ジャッジ結果
| セット名 |
Sample |
All |
| 得点 / 配点 |
0 / 0 |
500 / 500 |
| 結果 |
|
|
| セット名 |
テストケース |
| Sample |
example_00.txt, example_01.txt |
| All |
example_00.txt, example_01.txt, hand_00.txt, hand_01.txt, hand_02.txt, hand_03.txt, hand_04.txt, hand_05.txt, hand_06.txt, hand_07.txt, hand_08.txt, hand_09.txt, hand_10.txt, hand_11.txt, random_00.txt, random_01.txt, random_02.txt, random_03.txt, random_04.txt, random_05.txt, random_06.txt, random_07.txt, random_08.txt, random_09.txt, random_10.txt, random_11.txt, random_12.txt, random_13.txt, random_14.txt, random_15.txt, random_16.txt, random_17.txt, random_18.txt, random_19.txt, random_20.txt, random_21.txt |
| ケース名 |
結果 |
実行時間 |
メモリ |
| example_00.txt |
AC |
8 ms |
3504 KiB |
| example_01.txt |
AC |
2 ms |
3460 KiB |
| hand_00.txt |
AC |
2 ms |
3668 KiB |
| hand_01.txt |
AC |
2 ms |
3584 KiB |
| hand_02.txt |
AC |
5 ms |
3576 KiB |
| hand_03.txt |
AC |
4 ms |
3632 KiB |
| hand_04.txt |
AC |
2 ms |
3664 KiB |
| hand_05.txt |
AC |
26 ms |
5316 KiB |
| hand_06.txt |
AC |
22 ms |
5340 KiB |
| hand_07.txt |
AC |
3 ms |
3628 KiB |
| hand_08.txt |
AC |
42 ms |
7148 KiB |
| hand_09.txt |
AC |
2 ms |
3500 KiB |
| hand_10.txt |
AC |
2 ms |
3608 KiB |
| hand_11.txt |
AC |
6 ms |
3624 KiB |
| random_00.txt |
AC |
22 ms |
3476 KiB |
| random_01.txt |
AC |
33 ms |
5876 KiB |
| random_02.txt |
AC |
43 ms |
7012 KiB |
| random_03.txt |
AC |
2 ms |
3612 KiB |
| random_04.txt |
AC |
35 ms |
5716 KiB |
| random_05.txt |
AC |
43 ms |
6972 KiB |
| random_06.txt |
AC |
9 ms |
4004 KiB |
| random_07.txt |
AC |
37 ms |
6148 KiB |
| random_08.txt |
AC |
42 ms |
6892 KiB |
| random_09.txt |
AC |
2 ms |
3596 KiB |
| random_10.txt |
AC |
2 ms |
3460 KiB |
| random_11.txt |
AC |
2 ms |
3508 KiB |
| random_12.txt |
AC |
2 ms |
3664 KiB |
| random_13.txt |
AC |
31 ms |
5924 KiB |
| random_14.txt |
AC |
41 ms |
6924 KiB |
| random_15.txt |
AC |
2 ms |
3644 KiB |
| random_16.txt |
AC |
32 ms |
5912 KiB |
| random_17.txt |
AC |
42 ms |
6936 KiB |
| random_18.txt |
AC |
14 ms |
4540 KiB |
| random_19.txt |
AC |
32 ms |
5960 KiB |
| random_20.txt |
AC |
41 ms |
6948 KiB |
| random_21.txt |
AC |
16 ms |
3564 KiB |