コード
import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.NoSuchElementException; public class Main { private final int MOD = (int) (1e9 + 7); private final Combination combination = new Combination(400001, MOD); private void solve(FastScanner in, PrintWriter out) { int N = in.nextInt(); int K = in.nextInt(); long[] X = new long[N * 2]; long[] Y = new long[N * 2]; for (int i = 0; i < N; i++) { X[i] = in.nextInt(); Y[i] = in.nextInt(); } int px = in.nextInt(); int py = in.nextInt(); for (int i = 0; i < N; i++) { X[i] -= px; Y[i] -= py; X[i + N] = X[i]; Y[i + N] = Y[i]; } long ans = combination.get(N, K); int right = 0; for (int left = 0; left < N; left++) { right = Math.max(right, left + 1); while (right < left + N && X[left] * Y[right] - Y[left] * X[right] >= 0) { right++; } ans += MOD - combination.get(right - left - 1, K - 1); ans %= MOD; } out.println(ans % MOD); } class Combination { private long[] fact; private long[] invFact; private int MOD; public Combination(int max, int MOD) { this.MOD = MOD; long[] inv = new long[max + 1]; fact = new long[max + 1]; invFact = new long[max + 1]; inv[1] = 1; for (int i = 2; i <= max; i++) { inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD; } fact[0] = invFact[0] = 1; for (int i = 1; i <= max; i++) { fact[i] = fact[i - 1] * i % MOD; } for (int i = 1; i <= max; i++) { invFact[i] = invFact[i - 1] * inv[i] % MOD; } } public long get(int x, int y) { if (x < y || y < 0) { return 0; } return fact[x] * invFact[y] % MOD * invFact[x - y] % MOD; } } public static void main(String[] args) { PrintWriter out = new PrintWriter(System.out); new Main().solve(new FastScanner(), out); out.close(); } private static class FastScanner { private final InputStream in = System.in; private final byte[] buffer = new byte[1024]; private int ptr = 0; private int bufferLength = 0; private boolean hasNextByte() { if (ptr < bufferLength) { return true; } else { ptr = 0; try { bufferLength = in.read(buffer); } catch (IOException e) { e.printStackTrace(); } if (bufferLength <= 0) { return false; } } return true; } private int readByte() { if (hasNextByte()) { return buffer[ptr++]; } else { return -1; } } private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126; } private void skipUnprintable() { while (hasNextByte() && !isPrintableChar(buffer[ptr])) { ptr++; } } boolean hasNext() { skipUnprintable(); return hasNextByte(); } public String next() { if (!hasNext()) { throw new NoSuchElementException(); } StringBuilder sb = new StringBuilder(); int b = readByte(); while (isPrintableChar(b)) { sb.appendCodePoint(b); b = readByte(); } return sb.toString(); } long nextLong() { if (!hasNext()) { throw new NoSuchElementException(); } long n = 0; boolean minus = false; int b = readByte(); if (b == '-') { minus = true; b = readByte(); } if (b < '0' || '9' < b) { throw new NumberFormatException(); } while (true) { if ('0' <= b && b <= '9') { n *= 10; n += b - '0'; } else if (b == -1 || !isPrintableChar(b)) { return minus ? -n : n; } else { throw new NumberFormatException(); } b = readByte(); } } double nextDouble() { return Double.parseDouble(next()); } double[] nextDoubleArray(int n) { double[] array = new double[n]; for (int i = 0; i < n; i++) { array[i] = nextDouble(); } return array; } double[][] nextDoubleMap(int n, int m) { double[][] map = new double[n][]; for (int i = 0; i < n; i++) { map[i] = nextDoubleArray(m); } return map; } public int nextInt() { return (int) nextLong(); } public int[] nextIntArray(int n) { int[] array = new int[n]; for (int i = 0; i < n; i++) { array[i] = nextInt(); } return array; } public long[] nextLongArray(int n) { long[] array = new long[n]; for (int i = 0; i < n; i++) { array[i] = nextLong(); } return array; } public String[] nextStringArray(int n) { String[] array = new String[n]; for (int i = 0; i < n; i++) { array[i] = next(); } return array; } public char[][] nextCharMap(int n) { char[][] array = new char[n][]; for (int i = 0; i < n; i++) { array[i] = next().toCharArray(); } return array; } public int[][] nextIntMap(int n, int m) { int[][] map = new int[n][]; for (int i = 0; i < n; i++) { map[i] = nextIntArray(m); } return map; } } }