Notes

// from kmjp
// source: https://kmjp.hatenablog.jp/entry/2021/03/29/0900

ll mo=1000000007;
ll comb(ll N_, ll C_) {
	const int NUM_=400001;
	static ll fact[NUM_+1],factr[NUM_+1],inv[NUM_+1];
	if (fact[0]==0) {
		inv[1]=fact[0]=factr[0]=1;
		for (int i=2;i<=NUM_;++i) inv[i] = inv[mo % i] * (mo - mo / i) % mo;
		for (int i=1;i<=NUM_;++i) fact[i]=fact[i-1]*i%mo, factr[i]=factr[i-1]*inv[i]%mo;
	}
	if(C_<0 || C_>N_) return 0;
	return factr[C_]*fact[N_]%mo*factr[N_-C_]%mo;
}

// Something noteworthy is you have to calculate binomial coefficients modulo 3, 
// but you can't do it naively since n! = 0 mod3, ∀ n ≥ 3. 
// To get around this, keep track of the power of 3 in 𝑛! (say 𝑝) and the value of 𝑛! without any powers of 3.
// Or use Lucas theorem

// Lucas theorem for mod = 3
int C[3][3];

int getC(int n, int k) {
	if (k < 0 || k > n) return 0;
	int ans = 1;
	while(n > 0) {
		int x = n % 3;
		int y = k % 3;
		n /= 3;
		k /= 3;
		ans = (ans * C[x][y]) % 3;
	}
	return ans;
}

// inside main
    for (int i = 0; i < 3; i++)
		C[i][0] = C[i][i] = 1;
	for (int i = 1; i < 3; i++)
		for (int j = 1; j < i; j++)
			C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % 3;


// binary exponentiation
ll modpow(ll a, ll n) {
	ll r=1;
	while(n) r=r*((n%2)?a:1)%mo,a=a*a%mo,n>>=1;
	return r;
}
 
ll comb(int P_,int Q_) {
	if(P_<0 || Q_<0 || Q_>P_) return 0;
	ll p=1,q=1;
	Q_=min(Q_,P_-Q_);
	for(int i=1;i<=Q_;i++) p=p*P_%mo, q=q*i%mo,P_--;
	
	return p*modpow(q,mo-2)%mo;
}
 
void solve() {
	int i,j,k,l,r,x,y; string s;
	
	cin>>N>>M>>K;
	
	ll ret=0;
	FOR(i,N) {
		ll d=1LL*i*(i+1)/2%mo;
		d=d*M%mo*M%mo;
		ret+=d;
	}
	FOR(i,M) {
		ll d=1LL*i*(i+1)/2%mo;
		d=d*N%mo*N%mo;
		ret+=d;
	}
	
	cout<<ret%mo*comb(N*M-2,K-2)%mo<<endl;
}

TODO: https://codeforces.com/contest/1536/problem/F

Enumerative combinatorics

Catalan numbers

The Catalan numbers are a remarkable sequence of numbers that “solve” a number of seemingly unrelated counting problems.

https://atcoder.jp/contests/abc167/tasks/abc167_e

ABC 209 Problem C - Not Equal

You are given a sequence C of N integers. Find the number of sequences A of N integers satisfying all of the following conditions. 1 ≤ Aᵢ ≤ Cᵢ ( 1 ≤ i ≤ N ) Aᵢ ≠ Aⱼ ( 1 ≤ i < j ≤ N ) Since the count may be enormous, print it modulo (10⁹ + 7).

Solution: Sort Cᵢ in increasing order and Now for each of the index i we have max(0, Cᵢ - (i-1)) choices to choose the element. We can prove this because, after determining the first i − 1 elements A₁ , A₂ , … , the candidates for Aᵢ are 1 , 2 , … Cᵢ , except for A₁ , A₂ , … Aᵢ − 1 (which are all pairwise distinct and between 1 and Cᵢ , inclusive); namely there are (Cᵢ − i + 1) candidates. If however any i satisfies Cᵢ − i + 1 < 0, then the answer is 0 .

https://atcoder.jp/contests/abc209/tasks/abc209_c

Leetcode Paiting a grid with 3 different colors

Painting a m * n grid with three different colors such that no two adjacent cells have same color, Here 1 <= m <= 5 & 1 <= n <= 1000 since m is very small we can create a graph where each node denotes a column (c1, c2, c3, c4, c5) and count the number of columns compatible with this using dynamic programming.

https://leetcode.com/problems/painting-a-grid-with-three-different-colors/

class Solution {
public:
    int memo[1000][1024] = {};
    int m, n, MOD = 1e9 + 7;
    int colorTheGrid(int m, int n) {
        this->m = m; this->n = n;
        return dp(0, 0, 0, 0);
    }
    int dp(int c, int prevColMask, int r, int curColMask) {
        if (c == n) return 1; // Found a valid way
        if (r == 0 && memo[c][prevColMask]) return memo[c][prevColMask];
        if (r == m) return dp(c + 1, curColMask, 0, 0);
        int ans = 0;
        for (int i = 1; i <= 3; ++i) // Try colors i in [1=RED, 2=GREEN, 3=BLUE]
            if (getColor(prevColMask, r) != i && (r == 0 || getColor(curColMask, r-1) != i))
                ans = (ans + dp(c, prevColMask, r + 1, setColor(curColMask, r, i))) % MOD;
        if (r == 0) memo[c][prevColMask] = ans;
        return ans;
    }
    int getColor(int mask, int pos) { // Get color of the `mask` at `pos`, use 2 bits to store a color
        return (mask >> (2 * pos)) & 3;
    }
    int setColor(int mask, int pos, int color) { // Set `color` to the `mask` at `pos`, use 2 bits to store a color
        return mask | (color << (2 * pos));
    }
};

Probability of derangements is 1/e https://math.stackexchange.com/questions/399500/why-is-the-derangement-probability-so-close-to-frac1e

https://ico-official.com/assets/media/archive/ico-booklet-2020-en.pdf

Number of Integer solutions for the equation x1 + x2 + ... + xr = n and x >= 0 is C(n+r-1, r-1).

Proof: We can assume we want to arrange (r-1) + symbols and (n) 1's so it is (n-r+1)!/(n! (r-1)!).

If we want solutions such that x > 0, then it is arranging (r-1) + symbols into gaps of n 1's that is 1 x 1 x 1 .. x 1 we need to choose (r-1) x positions out of the available (n-1) positions and hence we have C(n-1, r-1)

REF: https://math.stackexchange.com/questions/919676/the-number-of-integer-solutions-of-equations

Problem based on this: https://atcoder.jp/contests/abc132/tasks/abc132_d

Colorful Hats 2

N people are standing in a queue, numbered 1 , 2 , 3 , . . . , N from front to back. Each person wears a hat, which is red, blue, or green.

The person numbered i says: "In front of me, exactly Ai people are wearing hats with the same color as mine."

Assuming that all these statements are correct, find the number of possible combinations of colors of the N people's hats. Since the count can be enormous, compute it modulo 1000000007 .

Solution

#include <iostream>
#include <string>
using namespace std;
#pragma warning (disable: 4996)

int N, A[1 << 18], C[3];
long long sum = 1;

int main() {
	cin >> N;
	for (int i = 1; i <= N; i++) cin >> A[i];

	for (int i = 1; i <= N; i++) {
		long long cnt = 0, id = -1;
		if (A[i] == C[0]) { cnt++; id = 0; }
		if (A[i] == C[1]) { cnt++; id = 1; }
		if (A[i] == C[2]) { cnt++; id = 2; }
		if (id == -1) {
			cout << "0" << endl;
			return 0;
		}
		sum *= cnt; C[id]++;
		sum %= 1000000007;
	}
	cout << sum << endl;
	return 0;
}

TODO: https://codeforces.com/contest/1549/problem/E