LightOJ 1122 - Digit Count
Given a set of digits S, and an integer n, you have to find how many n-digit integers are there, which contain digits that belong to S and the difference between any two adjacent digits is not more than two.
Input
Input starts with an integer T (≤ 300), denoting the number of test cases.
Each case contains two integers, m (1 ≤ m < 10) and n (1 ≤ n ≤ 10). The next line will contain m integers (from 1 to 9) separated by spaces. These integers form the set S as described above. These integers will be distinct and given in ascending order.
Output
For each case, print the case number and the number of valid n-digit integers in a single line.
Sample Input
3
3 2
1 3 6
3 2
1 2 3
3 3
1 4 6
Output for Sample Input
Case 1: 5
Case 2: 9
Case 3: 9
Note
For the first case the valid integers are
11
13
31
33
66
今天做hihoCoder碰到的一个题目,所用方法之前并不了解。所以,找了这题练练手
此题题解参考:http://www.cnblogs.com/aiterator/p/6685932.html
#include<bits/stdc++.h>
using namespace std;
typedef vector<unsigned int> vec;
typedef vector<vec> mat;
mat mul(mat &a, mat &b)
{
mat c(a.size(), vec(b[0].size(), 0));
for(int i=0; i<a.size(); ++ i)
{
for(int j=0; j<b[0].size(); ++ j)
{
for(int k=0; k<b.size(); ++ k)
c[i][j] = c[i][j] + a[i][k] * b[k][j];
}
}
return c;
}
mat pow(mat &a, unsigned int n)
{
mat b(a.size(), vec(a[0].size(), 0));
for(int i=0; i<a.size(); ++ i)
b[i][i] = 1;
while(n > 0)
{
if(n & 1)
b = mul(b, a);
a = mul(a, a);
n >>= 1;
}
return b;
}
void solve(int cases)
{
int m, n;
cin >> m >> n;
vec arr(m);
for(int i=0; i<m; ++ i)
cin >> arr[i];
sort(arr.begin(), arr.end());
mat a(m, vec(m, 0));
for(int i=0; i<m; ++ i)
{
for(int j=max(0, i-2); j<min(m, i+3); ++ j)
{
if(abs(arr[i] - arr[j]) <= 2)
a[i][j] = 1, a[j][i] = 1;
}
}
mat b(1, vec(m, 1));
mat c = pow(a, n-1);
mat d = mul(b, c);
unsigned int ans = 0;
for(int i=0; i<d[0].size(); ++ i)
ans += d[0][i];
cout << "Case " << cases+1 << ": " << ans << endl;
}
int main()
{
int t;
cin >> t;
for(int i=0; i<t; ++ i)
solve(i);
return 0;
}