Challenge: Beautiful Sets
Subdomeniu: Combinatorics (combinatorics)
Scor cont: 75.0 / 75
Submission status: Accepted
Submission score: 1.0
Submission ID: 464758111
Limbaj: cpp14
Link challenge: https://www.hackerrank.com/challenges/polita-sets/problem
Cerinta
Consider a set, $S$, consisting of $k$ integers. The set is *beautiful* if *at least one* of the following conditions holds true for every $x \in S$:
1. $x-1 \in S$
2. $x+1 \in S$
For example, $S = \{1, 2, 50, 51\}$ is *beautiful* but $S = \{1, 5, 9\}$ is *not beautiful*. Given two integers, $n$ and $k$, can you find the number of different $k$-element beautiful sets you can create using integers $\in [1, n]$?
Perform $q$ queries where each query $i$ consists of some $n_i$ and $k_i$. For each query:
- Find the number of different beautiful sets having exactly $k$ elements that can be generated using integers in the inclusive range from $1$ to $n$.
- Print the number of beautiful sets, modulo $10^9+7$, on a new line.
Input Format
The first line contains an integer, $q$, denoting the number of queries.
Each line $i$ of the $q$ subsequent lines consists of two space-separated positive integers describing the respective values of $n_i$ and $k_i$ for the query.
Output Format
For each query, print the number of different beautiful sets of size $k$ that can be generated using integers in the inclusive range from $1$ to $n$ on a new line. As the answers to these queries can be quite large, each answer must be modulo $10^9+7$.
Constraints
* $1 \le q \le 10$
* $1 \le n \le 10^6$
* $1 \le k \le n$
**Subtasks**
* $1 \le n \le 1000$ for $40\%$ of the maximum score.
Cod sursa
#include <bits/stdc++.h>
using namespace std;
static const long long MOD = 1000000007LL;
long long modPow(long long a, long long e) {
long long r = 1 % MOD;
a %= MOD;
while (e > 0) {
if (e & 1) r = (__int128)r * a % MOD;
a = (__int128)a * a % MOD;
e >>= 1;
}
return r;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int q;
cin >> q;
vector<pair<int, int>> qs(q);
int maxN = 0;
for (int i = 0; i < q; ++i) {
int n, k;
cin >> n >> k;
qs[i] = {n, k};
maxN = max(maxN, n);
}
vector<long long> fact(maxN + 1), ifact(maxN + 1);
fact[0] = 1;
for (int i = 1; i <= maxN; ++i) fact[i] = (__int128)fact[i - 1] * i % MOD;
ifact[maxN] = modPow(fact[maxN], MOD - 2);
for (int i = maxN; i >= 1; --i) ifact[i - 1] = (__int128)ifact[i] * i % MOD;
auto C = [&](int n, int r) -> long long {
if (r < 0 || r > n) return 0;
return (__int128)fact[n] * ifact[r] % MOD * ifact[n - r] % MOD;
};
for (auto qv : qs) {
int n = qv.first;
int k = qv.second;
if (k <= 1) {
cout << 0 << '\n';
continue;
}
long long ans = 0;
int rMax = min(k / 2, n - k + 1);
for (int r = 1; r <= rMax; ++r) {
long long waysBlocks = C(k - r - 1, r - 1); // split k ones into r runs, each >=2
long long waysPlace = C(n - k + 1, r); // place r runs in n slots
ans = (ans + (__int128)waysBlocks * waysPlace) % MOD;
}
cout << ans << '\n';
}
return 0;
}
HackerRank Combinatorics – Beautiful Sets
