Тренировка-2006-03-12 - Решение на C

от Съзтезателно програмиране

Направо към: навигация, търсене

Задачата е на практика математическа. Най-важното наблюдение е, че редът на буквите в една дума не е съществен, т.е. нужна ни е само хистограмата на думата - коя буква колко пъти се среща. Нека началната дума представим с вектора

<math>v = \begin{pmatrix}\alpha_1 \\ \alpha_2 \\ \vdots \\ \alpha_k \end{pmatrix}</math>, където <math>\alpha_i</math> е броят на срещанията на i-тата буква в началната дума (i = 0 <=> броят срещания на буквата 'a').

Нека запишем хистограмите на всяка "заместваща" дума в колоните на матрицата A:

<math>A = \begin{pmatrix} a_{1,1} & a_{1,2} & \cdots & a_{1,k} \\ a_{2,1} & a_{2,2} & \cdots & a_{2,k} \\ \vdots \\ a_{k,1} & a_{k,2} & \cdots & a_{k,k} \end{pmatrix}</math>, където <math>a_{i,j}</math> е броят букви i, които се генерират при едно заместване на буквата j със съответната й дума.

Лесно се вижда, че A.v е вектор-стълб, представляващ хистограмата на думата, която се получава от началната дума след заместване на всичките й букви със съответните им заместващи думи. Оттук по индукция следва, че в задачата се пита съдържанието на вектора x, където:

<math>x = A^m . v</math>

Оттук нататък задачата е лесна, като се използва бързия алгоритъм за повдигане на степен (тъй като m е до 10^9).

Примерно решение на C++

/* TASK: Replacement
   Author: Veselin Georgiev
*/
#include <iostream>
using namespace std;

#define MOD 987654321

int m, k;
char s[10000000];

class matrix {
	long long a[26][26];
	int n,m;
public:
	matrix(int _n, int _m, int fill = 1)
	{
		n = _n; m = _m; memset(a, 0, sizeof(a));
		if (n == m) 
			for (int i = 0; i < n; i++) a[i][i] = fill;
	}
	matrix operator *(const matrix &b)
	{
		matrix res(n, b.m, 0);
		for (int i = 0; i < n; i++)
			for (int j = 0; j < b.m; j++)
				for (int k = 0; k < b.n; k++) {
					res.a[i][j] += (a[i][k] * b.a[k][j]);
					res.a[i][j] %= (long long) MOD;
				}
		return res;
	}
	void insert_column(char *s)
	{
		for (int i = 0; i < n; i++) a[i][m] = 0;
		m++;
		for (int i = 0; s[i]; i++)
			a[s[i]-'a'][m-1]++;
	}
	int index(int i, int j) const { return a[i][j]; }
};

matrix power(const matrix & A, int exponent)
{
	matrix id(k, k);
	matrix mul = A;
	for (unsigned i = 1; i; i <<= 1) {
		if (i & m) id = id * mul;
		mul = mul * mul;
	}
	return id;
}

int main(void)
{
	while (1) {
		cin >> m >> k;
		if (k == 0) break;
		cin >> s;
		matrix init(k, 0);
		init.insert_column(s);
		matrix A(k, 0);
		for (int i = 0; i < k; i++)
		{
			cin >> s;
			A.insert_column(s);
		}
		matrix B = power(A, m);
		matrix res = B * init;
		for (int i = 0; i < k-1; i++)
			cout << res.index(i, 0) << " ";
		cout << res.index(k-1, 0) << endl;
		
	}
	return 0;
}
Лични инструменти