猜词次数


16

任务

给定2个正整数nk,其中n > k输出从一组可n区分元素到一组可k区分元素的排斥数。

定义

如果对于每个t∈T都有s∈S使得f(s)= t,则函数f:S→T被称为素射。

n=3和时k=2,输出为6,因为存在6{1,2,3}到的排斥{1,2}

  1. 1↦1, 2↦1, 3↦2
  2. 1↦1, 2↦2, 3↦1
  3. 1↦1, 2↦2, 3↦2
  4. 1↦2, 2↦1, 3↦1
  5. 1↦2, 2↦1, 3↦2
  6. 1↦2, 2↦2, 3↦1

测试用例

n k output
5 3 150
8 4 40824
9 8 1451520

参考

计分

这是。以字节为单位的最短答案将获胜。

有标准漏洞


11
排斥的定义会很好。
Stewie Griffin '18

3
n是否等于k是有意的吗?
丹尼斯

1
@丹尼斯我想从挑战中排除所有可能的极端情况
Leaky Nun

3
这似乎是一个重要的优势案例。我的猜测是,大多数适用于n> k的答案也适用于n == k,但它可能允许在某个地方偷偷摸摸打高尔夫球
dylnan

@谁投票关闭了你是什么原因?
dylnan '18

Answers:


5

果冻5 4字节

ṗṬML

这是O(k n蛮力解。

在线尝试!

怎么运行的

ṗṬML  Main link. Left argument: k. Right argument: n.

ṗ     Cartesian power; yield the list of all n-tuples over {1, ..., k}.
      Each tuple represents a (not necessarily surjective) function from
      {1, ..., n} to {1, ..., k}.
 Ṭ    Apply the "untruth" atom to each tuple.
      Ṭ maps a list of indices to an array with 1's at those indices, and exactly
      as many zeroes as needed to build the array.
      Examples:
           [1, 2, 3, 3, 3] -> [1, 1, 1]
           [1, 3, 5]       -> [1, 0, 1, 0, 1]
           [2, 6, 2, 4, 4] -> [0, 1, 0, 1, 0, 1]
  M   Yield all indices of maximal elements, i.e., all indices of [1] * k.
   L  Take the length.


4

精益,66字节

def s:_->nat->nat|(m+1)(n+1):=(n+1)*(s m n+s m(n+1))|0 0:=1|_ _:=0

在线尝试!


正确性证明

在线尝试!


说明

让我们取消功能:

def s : nat->nat->nat
| (m+1) (n+1) := (n+1)*(s m n + s m (n+1))
| 0     0     := 1
| _     _     := 0

该功能由模式匹配和递归定义,两者均具有内置支持。

我们定义s(m+1, n+1) = (n+1) * (s(m, n) + s(m, n+1)s(0, 0) = 1,这留下了s(m+1, 0)s(0, n+1),这两个定义0都由最后一种情况决定。

精益用途lamdba演算的语法,所以s m ns(m, n)


现在,证明正确性:我以两种方式陈述它:

def correctness : ∀ m n, fin (s m n) ≃ { f : fin m → fin n // function.surjective f } :=
λ m, nat.rec_on m (λ n, nat.cases_on n s_zero_zero (λ n, s_zero_succ n)) $
λ m ih n, nat.cases_on n (s_succ_zero m) $ λ n,
calc fin (s (nat.succ m) (nat.succ n))
   ≃ (fin (n + 1) × (fin (s m n + s m (n + 1)))) :
  (fin_prod _ _).symm
... ≃ (fin (n + 1) × (fin (s m n) ⊕ fin (s m (n + 1)))) :
  equiv.prod_congr (equiv.refl _) (fin_sum _ _).symm
... ≃ (fin (n + 1) × ({f : fin m → fin n // function.surjective f} ⊕
         {f : fin m → fin (n + 1) // function.surjective f})) :
  equiv.prod_congr (equiv.refl _) (equiv.sum_congr (ih n) (ih (n + 1)))
... ≃ {f // function.surjective f} : s_aux m n

def correctness_2 (m n : nat) : s m n = fintype.card { f : fin m → fin n // function.surjective f } :=
by rw fintype.of_equiv_card (correctness m n); simp

第一个是实际发生的情况:到之间的双射[0 ... s(m, n)-1]和从[0 ... m-1]到的双射[0 ... n-1]

第二个是通常所说的,即s(m, n)[0 ... m-1]到的基数的基数[0 ... n-1]


精益使用类型论作为基础(而不是集合论)。在类型论中,每个对象都有其固有的类型。nat是自然数的类型,并且0是自然数的语句表示为0 : nat。我们说这0是类型nat,并且nat具有0居民身份。

命题(陈述/断言)也是类型:其居民是命题的证明。


  • def:我们将介绍一个定义(因为双射实际上是一个函数,而不仅仅是命题)。

  • correctness:定义的名称

  • ∀ m n:对于每个mn(精益会自动推断出其类型为nat,这是由于以下原因)。

  • fin (s m n)是小于的自然数类型s m n。要成为居民,请提供一个自然数并证明其小于s m n

  • A ≃ B:类型A和类型之间的双射B。说双射是一种误导,因为实际上必须提供反函数。

  • { f : fin m → fin n // function.surjective f }fin m到的猜想类型fin n。此语法从类型构建子类型fin m → fin n,即,从函数类型fin mfin n。语法为{ var : base type // proposition about var }

  • λ m∀ var, proposition / type involving var实际上是一个函数,它var作为输入,因此λ m介绍输入。∀ m n,是简写∀ m, ∀ n,

  • nat.rec_on m:对进行递归m。为...定义事物,为m定义事物0,然后为它赋予事物k,为k+1。可能会注意到,这与归纳法相似,并且实际上这是由Church-Howard所致。语法为nat.rec_on var (thing when var is 0) (for all k, given "thing when k is k", build thing when var is "k+1")

嘿,这是越来越长,我只是在第三行correctness...


3

J,19个字节

-/@(^~*]!0{])],i.@-

在线尝试!

说明

-/@(^~*]!0{])],i.@-  Input: n (LHS), k (RHS)
                  -  Negate k
               i.@   Range [k-1, k-2, ..., 0]
             ]       Get RHS
              ,      Join, forms [k, k-1, ..., 0]
   (        )        Dyad between n (LHS), [k, k-1, ..., 0] (RHS)
           ]           Get RHS
         0{            Select value at index 0
       ]               Get RHS
        !              Binomial coefficient
    ^~                 Raise each in RHS to power of n
      *                Multiply
-/@                  Reduce from right to left using subtraction (forms alternating sum)

-/@(^~*]!0{])]-i.
FrownyFrog

2

R,49个字节

function(n,k,j=0:k)((-1)^(k-j)*j^n)%*%choose(k,j)

在线尝试!

实现Mario Catalani的公式之一:

T(n, k) = Sum_{j=0..k} (-1)^(k-j)*j^n*binomial(k, j)

或者:

T(n, k) = Sum_{j=0..k} (-1)^j*binomial(k, j)*(k-j)^n

在R中产生相同的字节数


2

Python 2中56个53 50字节

f=lambda n,k:n/k and(1/k or f(n-1,k-1)+f(n-1,k))*k

在线尝试!

-3个字节感谢H.PWiz。

-3个字节感谢Dennis。

  • 如果n<k不是所有的k都可以映射到那里,那么就不会有任何疑问。n/k and照顾这个。
  • 接受f(0,0)=1给了我们唯一需要的非零基本情况。1/k or实现这一目标。


2

Brain-Flak,142字节

({}<({}()){({}[(())]<<>{({}({})<>)<>}{}>)}{}>)<>{<>(({}<>)<{({}[()]<([])({([{}]()({}))([{}]({}))}{}[{}])>)}{}({}<>)>)<>}<>{}{}{({}<>[{}])<>}<>

在线尝试!

这使用标准的包含-排除公式。

我目前无法撰写完整的解释,但这是一个高级解释:

# Compute k-th row of Pascal's triangle
({}<({}()){({}[(())]<<>{({}({})<>)<>}{}>)}{}>)<>

# Multiply each element by n^j (and reverse to other stack)
{<>(({}<>)<{({}[()]<([])({([{}]()({}))([{}]({}))}{}[{}])>)}{}({}<>)>)<>}

# Compute alternating sum
<>{}{}{({}<>[{}])<>}<>


2

外壳,7个字节

#`¦ḣ¹π²

在线尝试!

说明

#`¦ḣ¹π²  Inputs: n (²), implicit k (¹)
     π²  Cartesian power of [1..k] to n
#        Count if:
   ḣ¹      Range [1..k]
 `¦        Is a subset


1

05AB1E,10个字节

sLsãʒêgQ}g

在线尝试!

说明

sLsã       # Cartesian product of range(k) repeated n times
    ʒ   }  # Filter by ...
     êgQ   # Connected uniquified length == k  (every item in range(k) appears at least once)
         g # Count
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.