Topics

The direct formula for derangements:

It is derived using the Inclusion-Exclusion Principle (IEP)

We need to count the number of ways to permute n elements such that no element appears in its original position.

Total ways to arrange n elements (without constraints) =

But we must remove cases where one or more elements stay fixed. This is where Inclusion-Exclusion comes in!

  1. Total ways to arrange n elements (ignoring restrictions):
  2. Subtract cases where at least one element stays in its original position:
    • Pick one element that remains fixed → Permute the remaining n-1 elements.
    • Ways to do this:
    • Since any of the n elements could be fixed, multiply by n:
  3. Add back cases where at least two elements remain fixed (over-subtracted before):
    • Choose two elements to stay fixed.
    • The remaining n-2 elements are freely permuted.
    • Ways to do this:
    • Ways to pick the 2 fixed elements:
    • So, the contribution is:
  4. Subtract cases where at least three elements remain fixed:
    • Choose three elements to stay fixed.
    • The remaining n-3 elements are freely permuted.
    • Ways to do this:
    • Ways to pick the 3 fixed elements:
    • So, the contribution is:
  5. Continue this process until all elements are fixed:
    • Every term alternates (adding and subtracting)
    • The general term follows:
    • Summing over all possible values of k, we get the final formula:

Tip

For large n, approaches (since the sum approaches )

#include <iostream>
#include <vector>
 
using namespace std;
 
long long power(long long base, long long exp, long long mod) {
    long long res = 1 % mod;
    base %= mod;
    while (exp > 0) {
        if (exp % 2 == 1) res = (res * base) % mod;
        base = (base * base) % mod;
        exp /= 2;
    }
    return res;
}
 
long long modInverse(long long n, long long mod) {
    return power(n, mod - 2, mod);
}
 
long long derangement(int n, long long mod) {
    vector<long long> fact(n + 1);
    fact[0] = 1;
 
    long long result = 1; // for k = 0: (-1)^0 / 0! = 1
 
    for (int k = 1; k <= n; ++k) {
        fact[k] = (fact[k - 1] * k) % mod; // calc factorial
        long long term = modInverse(fact[k], mod); // calc inverse
 
        if (k % 2 == 0) {
            result = (result + term) % mod;
        } else {
            result = (result - term + mod) % mod; // +mod to handle negative results
        }
    }
 
    result = (result * fact[n]) % mod;
    return result;
}
 
int main() {
    int n;
    long long mod = 1e9 + 7;
 
    cin >> n;
    cout << derangement(n, mod) << endl;
 
    return 0;
}