Откопал программку, которую писал на основе поддержки в теме
Перестановки в pari/gp (или где-нибудь еще). Сейчас уже практически ничего не помню, но что именно выводит программа распознал. А выводит она решения для конечных точек на специфических досках
заданной длины, базирующихся на двоичной записи
, о которых я писал выше. В конце добавил сумму всех решений по конечным точкам - это подпоследовательности
A329369.
Код:
default(parisizemax,10^9)
\\ увеличиваем объем выделяемой памяти
n=5
\\ задаем длину бинарного массива
n_fac=n!
v_bin=vector(2^(n-2),i,binary(2*(i-1+2^(n-2))));
\\ создаем все четные бинарные массивы длины n
v_perm=vector(n_fac,i,numtoperm(n,i-1));
\\ создаем все перестановки длины n
v_p_inv=vector(n_fac,i,vector(n));
\\ пустой массив для обратных перестановок
v_p_i_1=vector(n_fac,i,vector(n-1));
\\ пустой массив для сравнения их соседних элементов
v_p_last=vector(n_fac,i,vector(n));
\\ пустой массив для выделения в исходных перестановках конечных точек
v_l_sol=vector(2^(n-2),k,vector(n));
for(i=1,n_fac,for(j=1,n,v_p_inv[i][v_perm[i][j]]=v_perm[1][j]));
\\ находим обратные перестановки
for(i=1,n_fac,for(j=1,n-1,v_p_i_1[i][j]=if(v_p_inv[i][j+1]>v_p_inv[i][j],1,0)));
\\ сравниваем их соседние элементы
for(i=1,n_fac,for(j=1,n,v_p_last[i][j]=if(v_perm[i][j]==n,1,0)));
\\ выделяем в исходных перестановках конечные точки
v_1(k)={
my(v_b_inv=vector(n_fac,i,vector(n)),
\\ пустой массив для перестановок k-того бинарного массива
v_b_i_1=vector(n_fac,i,vector(n)),
\\ пустой массив для сравнения их с v_p_i_1
v_cond=vector(n_fac,i,0),
\\ пустой массив для выделения полного соответствия
v_cond_1=vector(n,j,0));
\\ пустой массив для подсчета количества решений для конечных точек
for(i=1,n_fac,for(j=1,n,v_b_inv[i][v_perm[i][j]]=v_bin[k][j]));
\\ переставляем k-тый бинарный массив каждой из n! исходных перестановок
for(i=1,n_fac,for(j=1,n,v_b_i_1[i][j]=if(j==n,if(v_b_inv[i][n]==0,1,0),if(v_b_inv[i][j]==v_p_i_1[i][j],1,0))));
\\ сравниваем элементы получившихся массивов и v_p_i_1
for(i=1,n_fac,v_cond[i]=if(sum(j=1,n,v_b_i_1[i][j])==n,1,0));
\\ выделяем полное соответствие
for(j=1,n,v_cond_1[j]=sum(i=1,n_fac,v_p_last[i][j]*v_cond[i]));
\\ считаем количество решений для j-той конечной точки
return(v_cond_1)}
for(k=1,2^(n-2),v_l_sol[k]=v_1(k));
print(v_l_sol)
a=vector(2^(n-2),i,0);
for(i=1,2^(n-2),a[i]=sum(k=1,n,v_l_sol[i][k]));
print(a)
Вкратце идея состоит в следующем. Берем некоторое
, например
. Генерируем массив перестановок длины 4 (длина 2-ной записи
плюс
). Пусть перестановка описывает последовательность посещения клеток. Не все перестановки описывают решения. Чтобы найти полезную перестановку необходимо произвести сверку, например:
1) Находим обратную перестановку, как перестановки, так и двоичной записи
:
2) Затемнаходим знаки первых разностей элементов обратной перестановки и присваиваем
если знак положительный,
если знак отрицательный.
подставляем и сравниваем с перестановкой двоичной записи:
Первые два элемента совпадают, третий - нет, значит перестановка бессмысленна. Если же совпадение полное, то перестановка описывает одно из решений, например
Аналогично для перестановок любой длины
. Важно помнить, что к 2-ной записи
всегда добавляем
в конце, т.е. это двоичная запись
. В рамках
A329369 учитываем решения, оканчивающиеся только на нулях (белые клетки, единицы - черные).