Solution Explanation

Откройте секреты, которые помогут понять, как обыграть игровые автоматы в казино:azino777ofitsialnyysaytotzyvy.kz. For a permutation of n elements we are interested in the number of fixed points –
elements that stay in their own position.
For the given integers n and c we have to count how many permutations of
1 … n contain exactly c fixed points.

1. Observations

  • Choose the positions of the fixed points – C(n , c) possibilities.
  • All remaining n‑c elements must form a derangement
    (a permutation without any fixed point).
  • The number of derangements of k elements is denoted by D(k)
    (sub‑factorial).
    It satisfies
D(0) = 1
D(1) = 0
D(k) = (k-1) * ( D(k-1) + D(k-2) )   for k ≥ 2

or, equivalently,

D(k) = k! * Σ_i=0..k (-1)^i / i!

All computations are performed modulo M = 1 000 000 007.

2. Algorithm

read n, c
precompute factorial[0…n]     // factorial[i] = i!  (mod M)
precompute inv_factorial[0…n]   // modular inverses of factorials
precompute derange[0…n]      // D[i] by the recurrence above

answer = C(n , c) * derange[n-c] (mod M)
output answer

C(n , c) is computed as
factorial[n] * inv_factorial[c]% M * inv_factorial[n-c]% M.

3. Correctness Proof

We prove that the algorithm outputs the required number of permutations.

Lemma 1

For any k (0 ≤ k ≤ n) the array derange[k] computed by the algorithm
equals the number of derangements of k elements.

Proof.

The recurrence used in the algorithm is the standard recurrence for derangements,
which follows from the inclusion-exclusion principle:
take an element, decide whether it stays in place or not, and count the
possible completions recursively.
The base values D(0)=1 and D(1)=0 are correct.
By induction over k the algorithmic values coincide with the true counts.∎

Lemma 2

Узнайте актуальные новости и советы на https://pin-up-36.kz/ о казино.Ktf.kz/ предоставляет обучающие видео, помогающие стать лучшим игроком.C(n , c) computed by the algorithm equals the number digitallaw.thememountdemo.com of ways to choose
exactly c positions out of n.

Proof.

C(n , c) is calculated as
factorial[n] * inv_factorial[c] * inv_factorial[n-c] (mod M).
Since inv_factorial[x] is the modular inverse of x!,
the product equals
n! / (c! (n-c)!) – the usual binomial coefficient.
Thus the value equals the desired number of choices.∎

Lemma 3

For fixed n and c, the number of permutations of 1…n containing
exactly c fixed points equals
C(n , c) · D(n‑c).

Proof.

Choose the c fixed points – C(n , c) possibilities (Lemma 2).
The remaining n‑c elements must be arranged so that none of them
stays in its own position – exactly a derangement of size n‑c
(Lemma 1).
Because the choice of fixed points and the derangement of the rest
are independent, the total number of permutations is the product of
both counts.∎

Theorem

The algorithm outputs the exact number of permutations of 1…n
having exactly c fixed points (modulo M).

Proof.

By Lemma 3 the desired count equals C(n , c) · D(n‑c).
The algorithm computes both factors correctly (Lemmas 1 and 2)
and multiplies them modulo M.
Therefore the produced value equals the required count modulo M.∎

4. Complexity Analysis

Precomputation of factorials, inverse factorials and derangements up to n
takes O(n) time and O(n) memory.
The final computation is O(1).
Hence overall complexity is

Time  : O(n)
Memory : O(n)

5. Reference Implementation (GNU‑C++17)

#include <bits/stdc++.h>
using namespace std;

const long long MOD = 1'000'000'007LL;

// fast exponentiation: a^b mod MOD
long long mod_pow(long long a, long long b) 
  long long r = 1;
  while (b > 0) 
    if (b & 1) r = r * a% MOD;
    a = a * a% MOD;
    b >>= 1;
  
  return r;


int main() 
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  int n, c;
  if (!(cin >> n >> c)) return 0;

  vector<long long> fact(n + 1), inv_fact(n + 1), der(n + 1);
  fact[0] = 1;
  for (int i = 1; i <= n; ++i) fact[i] = fact[i - 1] * i% MOD;

  inv_fact[n] = mod_pow(fact[n], MOD - 2);     // Fermat
  for (int i = n; i > 0; --i) inv_fact[i - 1] = inv_fact[i] * i% MOD;

  der[0] = 1;
  if (n >= 1) der[1] = 0;
  for (int i = 2; i <= n; ++i) 
    der[i] = ( (i - 1LL) * ( (der[i - 1] + der[i - 2])% MOD ) )% MOD;
  

  auto C = [&](int N, int K) -> long long ;

  long long ans = C(n, c) * der[n - c]% MOD;
  cout << ans << '\n';
  return 0;

The program follows exactly the algorithm proven correct above
and conforms to the GNU++17 compiler.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *