Somme circolari limitate


10

Sfida

Immaginiamo una Ntupla di numeri interi compresi tra 0 e Minclusi e chiamiamola F.

Ci sono (M + 1) ** Npossibili Fin totale.

Quanti di questi Fsoddisfano tutte le seguenti disuguaglianze (l'indice è basato su una base)?

  • F[n] + F[n+1] <= M per 1 <= n < N
  • F[N] + F[1] <= M

Scrivere un programma o funzione che prende due interi positivi N e Med emette la risposta in qualsiasi forma conveniente.

Casi test

(N,M) => Answer

(1,1) => 1
(2,1) => 3
(3,1) => 4
(4,1) => 7

(1,2) => 2
(2,2) => 6
(3,2) => 11
(4,2) => 26

(10,3) => 39175
(10,4) => 286555
(10,5) => 1508401

(25,3) => 303734663372
(25,4) => 43953707972058
(25,5) => 2794276977562073

(100,3) => 8510938110502117856062697655362747468175263710
(100,4) => 3732347514675901732382391725971022481763004479674972370
(100,5) => 60964611448369808046336702581873778457326750953325742021695001

Spiegazione

M (max value of element) = 1

F[1] + F[1] <= 1; F = [0]
(1,1) => 1

F[1] + F[2] <= 1; F = [0,0], [0,1], [1,0]
(2,1) => 3

F = [0,0,0], [0,0,1], [0,1,0], [1,0,0]
(3,1) => 4

F = [0,0,0,0], [0,0,0,1], [0,0,1,0], [0,1,0,0], [0,1,0,1], [1,0,0,0], [1,0,1,0]
(4,1) => 7

---

M = 2

F[1] + F[1] <= 2; F = [0], [1]
(1,2) => 2

F = [0,0], [0,1], [0,2], [1,0], [1,1], [2,0]
(2,2) => 6

F = [0,0,0], [0,0,1], [0,0,2], [0,1,0], [0,1,1], [0,2,0], [1,0,0], [1,0,1],
[1,1,0], [1,1,1], [2,0,0]
(3,2) => 11

(4,2) => 26 (left as exercise for you)

Regole

  • Questa è una sfida a . La complessità temporale del codice dovrebbe essere polinomiale MeN (ad es. Non è possibile generare tutte le (M + 1) ** Ntuple e quindi verificare la condizione). Spiega il tuo approccio durante l'invio.
  • Si applicano le regole standard del . Vince la risposta più breve in byte.

Risposte:


7

Python con numpy , 59 byte

lambda M,N:trace(mat(tri(M+1)[::-1])**N)
from numpy import*

Provalo online!

Utilizza la moltiplicazione matriciale per contare i percorsi. Se la precisione float è un problema, matpotrebbe specificare mat(...,int).


L'uso mat(...,int)non sembra funzionare per i n=100casi. Il metodo è corretto (usare sympy per sommare i poteri delle radici del polinomio caratteristico funziona, per esempio), ma intorpidimento va storto da qualche parte man mano che i numeri aumentano (forse è l' **operatore elettrico?)
Jonathan Allan

4

Pyth , 27 byte

.N?Ys:RTtYh-QNgQ+NTs:Rdtszh

Dimostrazione

Si aspetta input nel formato:

M
N

Questa è la classica programmazione dinamica, sull'estremità sinistra dei valori impostati finora, sull'estremità destra e sull'attuale dimensione del gap.

Come funziona, in pseudocodice / Python:

.N          | define memoized fill(left, right, gap):
?           | if cap > 0 then
s:RTtY      | sum(fill(i, right, gap - 1)
h-QN        |     for i in range(M - left + 1))
gQ+NT       | else M >= left + right
            | output:
s:Rdtsz     | sum(fill(i, i, N - 1)
h           |     for i in range(M + 1))

Qè usato per M, zè usato per N, :è fill, Nè left, Tè right, Yè gap.


4

MATL , 13 12 byte

Q:&>~PiY^Xds

Provalo online! Questa è una traduzione diretta della risposta Python di xnor e della mia prima risposta MATL, quindi molto probabilmente non è ottimale. Ad esempio, c'è probabilmente un modo più breve per ottenere una matrice triangolare in alto a sinistra rispetto a t&lYRP. Modifica: E si scopre che c'è, vale a dire :&>~P. Grazie a Luis Mendo per -1 byte!

               M is the first input and N the second
Q:             increment M and generate range from 1 to M+1
  &>           compare vector element wise with itself with greater-than function
               results in a upper-right triangular matrix
    ~          inverse to get lower-left triangular matrix
     P         flip rows to get upper-left triangular matrix
      i        input N
       Y^      take the matrix to the power of N
         Xds   compute the sum of the main diagonal

@LuisMendo Grazie! Anche se è solo un byte o c'è qualcos'altro che può essere eliminato?
Laikoni,

1
No, tutto qui, non posso contare MrGreen
Luis Mendo,

2

Stax , 17 byte

°(√&╒íƽ╨⌂'├╖▼1_Z

Esegui ed esegui il debug

Disimballato, non golfato e commentato, sembra così.

^1](    [1, 0, ... 0] with M zeroes
:)      get all rotations of the array
{       begin block
  {:+rm map each array to reverse(prefixSums(arr))
},v*    execute preceding block N-1 times
F       for each array, execute the rest of the program
  iT    remove the last i elements from the array, where i is the iteration index
  F+    add the remaining elements to the running total
        implicitly print output

Esegui questo


2

R , 72 byte

function(M,N)sum(diag(Reduce(`%*%`,rep(list(outer(0:M,0:M,"+")<=M),N))))

Provalo online!

Ports xnor's approach.

Non riesce per casi di test più grandi in quanto R ha solo il supporto di numeri interi a 32 bit (vengono lanciati doublequando viene raggiunto il valore int massimo), quindi gmpsarebbe necessario utilizzare o un'altra libreria aritmetica di precisione arbitraria.

Stranamente, R manca di un operatore di potenza a matrice, come ^sempre si applica elementally.


In realtà, %^%nel pacchetto è presente un operatore correttamente implementato expmche consentirebbe -5 byte , ma sfortunatamente non è disponibile su TIO (ho dovuto testare localmente).
Kirill L.,

@KirillL. sì, l'avevo considerato, ma penso che rimarrò fedele alla mia risposta R di base. Inoltre puoi giocare a golf fino a 60 byte non caricando l'intero pacchetto:function(M,N)sum(diag(expm::`%^%`(outer(0:M,0:M,"+")<=M,N)))
Giuseppe,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.