Challenge: Towers

Subdomeniu: Combinatorics (combinatorics)

Scor cont: 80.0 / 80

Submission status: Accepted

Submission score: 1.0

Submission ID: 464736395

Limbaj: cpp14

Link challenge: https://www.hackerrank.com/challenges/towers/problem

Cerinta

One day John had to take care of his little nephew Jim. He was very busy, so he gave Jim a big bag full of building bricks. The bricks are of various heights: at most 15 different heights. For each height, the bag contains infinitely many bricks.   
<br>
Now, Jim’s task is to build every possible tower of height $N$ from the given bricks. Bricks are stacked vertically only and stand in an upright position. Two towers are different if their brick height sequences are different.
<br>
Jim is good at building towers and can build one tower in exactly 2 minutes, regardless of its height. John wants to know the time Jim requires to build all possible towers.  

**Input Format**  
There are $3$ lines of input. First line contains an integer, $N$, the height of tower to be built. Second line contains another integer, $K$, which represents different heights of bricks available in the bag. Third line contains $K$ distinct integers representing the available heights.  


**Output Format**  
In one line print the number of minutes Jim requires to build all possible towers. As this number can be very large, print the number modulo $(10^9+7)$.  


**Constraints**  
$1 \le N \le 10^{18}$  
$1 \le K \le 15$  
All heights will be unique.  
Height of each brick will lie in range [1, 15].  

**Sample Input#00**

    10
    1
    1

**Sample Output#00**  

    2

**Explanation#00:**  There is exactly one type of brick, so there is exactly one tower of height 10. Building any tower takes 2 minutes, so the answer is 2.

**Sample Input#01**  

    5
    2
    2 3

**Sample Output#01**  

    4

**Explanation #01:** There are two types of bricks. There are two different towers of height 5 which can be build from these types of bricks: $[2,3]$ and $[3,2]$. They are different, because the sequence of bricks in them is different. Building any tower takes 2 minutes, so the answer is $2 \times 2 = 4$.

**Sample Input#03**  

    19
    2
    4 5

**Sample Output#03**

    8

**Explanation #03:** There are two types of bricks. Jim can build 4 different towers of height $19$ from these bricks: $[5,5,5,4]$, $[5,5,4,5]$, $[5,4,5,5]$ and $[4,5,5,5]$. Building any tower takes 2 minutes, so the answer is $2 \times 4 = 8$.

Cod sursa

//towers.cpp
//Towers
//Weekly Challenges - Week 10
//Author: derekhh

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

const int MOD = 1000000007;

struct Type
{
	int val[15][15];
} mat;

Type mul(Type a, Type b)
{
	Type ret;
	memset(ret.val, 0, sizeof(ret.val));
	for (int i = 0; i < 15; i++)
		for (int j = 0; j < 15; j++)
			for (int k = 0; k < 15; k++)
				ret.val[i][j] = (ret.val[i][j] + (long long) a.val[i][k] * b.val[k][j]) % MOD;
	return ret;
}

Type pow(Type a, long long n)
{
	Type ret;
	memset(ret.val, 0, sizeof(ret.val));
	for (int i = 0; i < 15; i++)
		ret.val[i][i] = 1;
	while (n != 0)
	{
		if (n % 2 == 1)
			ret = mul(ret, a);
		a = mul(a, a);
		n /= 2;
	}
	return ret;
}

int main()
{
	long long n, k;
	cin >> n >> k;
	memset(mat.val, 0, sizeof(mat.val));
	for (int i = 0; i < k; i++)
	{
		int h;
		cin >> h;
		mat.val[0][h - 1] = 1;
	}
	for (int i = 1; i <= 14; i++)
		mat.val[i][i - 1] = 1;
	Type ret = pow(mat, n);
	cout << (ret.val[0][0] * 2) % MOD << endl;
	return 0;
}
HackerRank Combinatorics – Towers