Challenge: Permutation Problem

Subdomeniu: Combinatorics (combinatorics)

Scor cont: 60.0 / 60

Submission status: Accepted

Submission score: 1.0

Submission ID: 464734952

Limbaj: cpp14

Link challenge: https://www.hackerrank.com/challenges/permutation-problem/problem

Cerinta

How many n-digit numbers (without leading zeros) are there such that no digit occurs more than k times?  

As the count of such n-digit numbers can be very large, print the answer mod (10<sup>9</sup>+7)  

**Input Format**  

The first line contains an integer, _T_ , the number of test cases. This is followed by _T_ lines each containing 2 space separated integers, _n_ and _k_  


**Constraints**  

_T_ ≤ 100000  
1 ≤ _n_ ≤ 1000  
1 ≤ _k_ ≤ 10<sup>9</sup>

**Sample Input**

    2
    2 3
    2 1

**Sample Output**

    90
    81

**Explanation**  
Case 1: A number can appear three times. So we have 9 (all except 0) numbers for first digit and 10 numbers for the second digit.  
Case 2: A number can appear only once. So we have 9 choices for the first digit and 9(all except the first one) for the second digit.

Cod sursa

//permutation-problem.cpp
//Permutation Problem
//Ad Infinitum - Math Programming Contest June'14
//Author: derekhh

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

const int MOD = 1000000007;

int f[1001][1001][11], g[1001][1001], c[1001][1001];

void init()
{
	for (int i = 1; i <= 1000; i++)
		c[i][0] = 1, c[i][1] = i, c[i][i] = 1;

	for (int i = 2; i <= 1000; i++)
		for (int j = 2; j <= 1000; j++)
			c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % MOD;
}

int foo(int i,int j,int k)
{
	if (f[i][j][k] != -1) return f[i][j][k];
	if (i == 0) return f[i][j][k] = 1;

	int val1 = (k * (long long)foo(i - 1, min(i - 1, j), k)) % MOD;
	int val2 = (k * (long long)c[i - 1][j]) % MOD;
	int val3 = ((long long)val2 * foo(i - j - 1, min(i - j - 1, j), k-1)) % MOD;
	
	return f[i][j][k] = (val1 + MOD - val3) % MOD;
	
	/*
	int ret = 0;
	for (int l = 1; l <= min(i, j); l++)
		ret = (ret + (long long)c[i][l] * foo(i - l, min(i - l, j), k - 1)) % MOD;
	return f[i][j][k] = ret;
	*/
}

int main()
{
	memset(f, -1, sizeof(f));
	init();

	for (int i = 1; i <= 1000; i++)
	{
		for (int j = 1; j <= i; j++)
		{
			for (int k = 1; k <= 10; k++)
			{
				f[i][j][k] = foo(i, j, k);
			}
		}
	}

	for (int i = 1; i <= 1000; i++)
	{
		for (int j = 1; j <= i; j++)
		{
			int val1 = (9 * (long long)foo(i - 1, min(i - 1, j), 10)) % MOD;
			int val2 = (9 * (long long)c[i - 1][j]) % MOD;
			int val3 = ((long long)val2 * foo(i - j - 1, min(i - j - 1, j), 9)) % MOD;
			g[i][j] = (val1 + MOD - val3) % MOD;
		}
	}
	int t;
	cin >> t;
	while (t--)
	{
		int n, k;
		cin >> n >> k;
		cout << g[n][min(n, k)] << endl;
	}
	return 0;
}
HackerRank Combinatorics – Permutation Problem