CJam (69 байт)
]qi:X,{1e|,:):N{N\f{1$%!*}W$.*:+}%1$W%.*:+N,/+}/W\+_1,*X=\_W%.*:+-Y/z
Онлайн демо
объяснение
Основная идея заключается в реализации функции генерации, описанной в OEIS. Входные данные являются неприятным особым случаем, но последние изменения, которые я сделал, в итоге привели к для этого случая, поэтому (для абсолютного значения) приводит их в порядок. Это самый странный трюк здесь.0−1z
.*:+
повторяется три раза и выглядит так, как если бы он был извлечен как {.*:+}:F~
. Однако это нарушает особый случай , потому что он вообще не выполняет внешний цикл.0
Мы используем вспомогательную функцию генерации для A000081 , члены которой имеют повторение
a[0] = 0
a[1] = 1
For n >= 1, a[n+1] = (sum_{k=1}^n a[n-k+1] * sum_{d|k} d * a[d]) / n
Я уверен, что некоторые языки имеют встроенные модули для обратного преобразования Мёбиуса , но CJam этого не делает; лучший подход я нашел , чтобы построить массив отображения к а затем сделать точечное умножение с использованием . Обратите внимание , что здесь удобно выстроили начиная с индекса 1, потому что мы хотим , чтобы избежать деления на ноль при настройке весов. Также обратите внимание, что если два массива, предоставленные для точечной операции, не имеют одинаковую длину, то значения из более длинного остаются нетронутыми: поэтому мы должны либо взять первые членов либо сделать так, чтобы массив весов поднялся до∑d∣kd×a[d]dk % d == 0 ? d : 0
a.*
akan, Последний кажется короче. Так что это обратное преобразование Мёбиуса дляN\f{1$%!*}W$.*:+
Если мы назовем результат обратного преобразования Мёбиуса M
, теперь у нас
a[n+1]=1n∑k=1na[n−k+1]×M[k]
Числитель, очевидно, является термином из свертки, поэтому мы можем обработать его путем обращения либо копии либо а затем поточечного умножения и суммирования. Опять же, наш индекс варьируется от до , и, кроме того, мы хотим объединить индексы, которые составляют , поэтому снова удобно индексировать с 1, а не с 0. Теперь мы учлиaM1nn+1a
qi:X,{ ,:):N{N\f{1$%!*}W$.*:+}%1$W%.*:+N,/+}/
Точка вспомогательной производящей функции задается разделом формулы A000055:
G.f.: A(x) = 1 + T(x) - T^2(x)/2 + T(x^2)/2,
where T(x) = x + x^2 + 2*x^3 + ... is the g.f. for A000081.
В терминах это означает, что искомый результат равенa
[x=0]+a[x]+12(a[x/2]−∑i=0na[i]×a[n−i])
где для с нечетным мы получаем 0. Самый короткий способ, который я нашел для этого, состоит в том, чтобы надуть нули ( ), а затем взять X-й элемент ( ).a[x/2]x1,*
X=
Обратите внимание, что сумма является еще одной сверткой, но на этот раз удобно индексировать от 0. Очевидное решение есть 0\+
, но здесь есть небольшая оптимизация. Поскольку , два члена свертки гарантированно равны нулю. Мы могли бы использовать это как возможность индексировать от 1, но особый случай становится безобразным. Если мы вместо того, чтобы делать , свертка дает нам и после вычитания и деления на мы обработали термин вне суммы, а также.X = 0 - 2 a [ x ] + ∑ n i = 0 a [ i ] × a [ n - i ] 2 a [ x ]a[0]=0X=0W\+
−2a[x]+∑ni=0a[i]×a[n−i]2a[x]
Итак, мы объяснили
qi:X,{ ,:):N{N\f{1$%!*}W$.*:+}%1$W%.*:+N,/+}/W\+_1,*X=\_W%.*:+-Y/
Остальные детали относятся к особому случаю. Первоначально я следовал за повторением более строго, начиная с 1]
и повторяя с сN=1
1]qi:X,1>{ ... }/
В результате, когда , мы вычисляем как : на один член больше, чем нам нужно. Инфляция и свертка приводят к результату . (Возможно, лучше, чем мы заслуживаем - это то, что мы должны иметь, потому что мы ничего не сделали с термином ). Таким образом, мы исправим это для трех символов либо как финал, либо используя стандартную технику «отступления» как .a 0 [ x = 0 ]X=0a[-1 1]
0[x=0]X!+
1e|
Чтобы получить «правильную» длину нам нужно не указывать эту начальную и вместо этого производить ее из основного цикла с . Совершенно просто1 Н = 0a1N=0
]qi:X,{ ... /+}/
очевидно дает деление на ноль. Но если мы попробуем
]qi:X,{1e| ... /+}/
тогда это работает. Мы получаем
e# Stack: [] 0
1e| e# Stack: [] 1
,:):N e# Stack: [] [1]
{ e# We only execute this loop once
N\f{1$%!*} e# 1 divides 1, so stack: [] [1]
W$.* e# Remember: if the two arrays supplied to the pointwise operation
e# are not the same length then the values from the longer one are
e# left untouched. Stack: [] [1]
:+ e# Fold over a singleton. Stack: [] 1
}% e# And that was a map, so stack: [] [1]
1$W%.*:+ e# Another [1] [] .*:+, giving the same result: 1
N,/ e# 1 / 1 = 1
+ e# And we append 1 to a giving [1]
который производит именно то значение, которое нам требуется.
Теперь, если этот основной цикл никогда не выполняется, поэтому после того, как мы введем в нижней части, мы получим . В итоге мы вычисляем , что не правильно. Но в то время как исправление от до заняло три символа, исправление от до принимает только один: дает абсолютное значение.- 1 ( - 1 - 1X=0−1[-1]
01-11(−1−12(−1×−1))=−101−11z