Challenge: Polygons
Scor cont: 80.0 / 80
Submission status: Accepted
Submission score: 1.0
Submission ID: 464761891
Limbaj: cpp14
Link challenge: https://www.hackerrank.com/challenges/polygons/problem
Cerinta
Consider a regular polygon with N vertices labelled 1..N. In how many ways can you draw K diagonals such that no two diagonals intersect at a point strictly inside the polygon? A diagonal is a line segment joining two non adjacent vertices of the polygon.
**Input:**
The first line contains the number of test cases T. Each of the next T lines contain two integers N and K.
**Output:**
Output T lines, one corresponding to each test case. Since the answer can be really huge, output it modulo 1000003.
**Constraints:**
1 <= T <= 10000
4 <= N <= 10^9
1 <= K <= N
**Sample Input:**
3
4 1
5 2
5 3
**Sample Output:**
2
5
0
**Explanation:**
For the first case, there are clearly 2 ways to draw 1 diagonal - 1 to 3, or 2 to 4. (Assuming the vertices are labelled 1..N in cyclic order).
For the third case, at most 2 non-intersecting diagonals can be drawn in a 5-gon, and so the answer is 0.
Cod sursa
#include <bits/stdc++.h>
using namespace std;
static const int MOD = 1000003;
long long modpow(long long a, long long e) {
long long r = 1 % MOD;
a %= MOD;
while (e > 0) {
if (e & 1) r = (r * a) % MOD;
a = (a * a) % MOD;
e >>= 1;
}
return r;
}
long long modinv(long long a) {
a %= MOD;
if (a < 0) a += MOD;
return modpow(a, MOD - 2);
}
vector<int> fact;
long long vp_fact(long long n) {
long long e = 0;
while (n > 0) {
n /= MOD;
e += n;
}
return e;
}
long long fact_no_p(long long n) {
if (n == 0) return 1;
long long q = n / MOD;
long long r = n % MOD;
long long res = fact_no_p(q);
if (q & 1LL) res = res * (MOD - 1) % MOD; // Wilson block sign
res = res * fact[(int)r] % MOD;
return res;
}
struct BinomPE {
long long unit; // binomial with p-factors removed, modulo p
long long exp; // exponent of p in binomial
};
BinomPE binom_pe(long long n, long long k) {
if (k < 0 || k > n) return {0, (long long)4e18};
long long e = vp_fact(n) - vp_fact(k) - vp_fact(n - k);
long long a = fact_no_p(n);
long long b = fact_no_p(k);
long long c = fact_no_p(n - k);
long long u = a;
u = u * modinv(b) % MOD;
u = u * modinv(c) % MOD;
return {u, e};
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
fact.assign(MOD, 1);
for (int i = 1; i < MOD; ++i) fact[i] = (long long)fact[i - 1] * i % MOD;
int T;
cin >> T;
while (T--) {
long long n, k;
cin >> n >> k;
if (k < 0 || k > n - 3) {
cout << 0 << '\n';
continue;
}
// D(n,k) = C(n+k-1,k) * C(n-3,k) / (k+1)
auto c1 = binom_pe(n + k - 1, k);
auto c2 = binom_pe(n - 3, k);
long long den = k + 1;
long long ed = 0;
while (den % MOD == 0) {
den /= MOD;
++ed;
}
long long et = c1.exp + c2.exp - ed;
if (et > 0) {
cout << 0 << '\n';
continue;
}
// Integer guarantees et >= 0.
long long ans = c1.unit;
ans = ans * c2.unit % MOD;
ans = ans * modinv(den % MOD) % MOD;
if (ans < 0) ans += MOD;
cout << ans << '\n';
}
return 0;
}
HackerRank Geometry – Polygons
