LoginSignup
0
0

CodeIQ:「ペア・ドロップ」問題の解答

Posted at

Kawazoe(@riverplus)さん出題の問題です。
問題とテストケースはこちらのお世話になりました。解答もあります。
->https://blog.goo.ne.jp/r-de-r/e/3f51395af1c1d9b98d6c2488ab3aa3c9

Aがk枚残ればBもk枚のこり、ペアの枚数もAと同数です。
Aのペアの組数 x=(n-k)/2=div(n-k,2)としますと
Aのペアの組み合わせの数はn組からx組選ぶ場合の数 -> nCx
Bのペアの組み合わせの数はn-x組からx組選ぶ場合の数 -> (n-x)Cx
残りk組は2枚のカードを区別するのでどちらがAに行くか -> 2^k
全体の組み合わせの数 -> (2*n)Cn
となり、
F(n,k)=nCx * (n-x)Cx * 2^k / (2*n)Cn

計算途中巨大な数になりますのでJuliaではBigIntが必要でしたが、
nCrに対応するbinomialという関数がありますので楽です。

#julia ver 1.41,1.53,1.73

function solve(n,k,a)
    n = BigInt(n)
    k = BigInt(k)
    x = div(n-k,2)
    ret = Int(trunc(binomial(n,x) * binomial(n-x,x) * 2^k / binomial(2*n,n) * 10^6))
   s = a == ret ? "ok " : "no "
   println(s,ret)
end

solve(2, 2,666666)
solve(4, 2,685714)
solve(5, 1,238095)
solve(13, 9,211187)
solve(30, 20,67130)
solve(41, 17,126481)
solve(80, 24,226)
solve(99, 47,137249)

場合の数の数え方はいろいろあって
ペアでないカードはn組からk組を選び2枚を区別するので組み合わせの数 -> nCk * 2^k
Aのペアはn-k組からx組選ぶので組みあわせの数 -> (n-k)Cx
全体の組み合わせの数 -> (2*n)Cn 
F(n,k)=nCk * 2^k * (n-k)Cx / (2*n)Cn
等でも良いのでPrologではこちらの式を使いました。

%SWI-Prolog ver 7.42,7.64

%:-initialization(start).   %ideone
%start.

ncr(_,0,1).
ncr(N,1,R):-R is N.
ncr(N,M,R):-N1 is N-1,M1 is M-1,ncr(N1,M1,R1),R is R1*N div M,!.

res(N,K,R):-
    N1 is N-K,N2 is (N-K)/2,ncr(N,K,R1),ncr(N1,N2,R2),ncr(2*N,N,R3),
    R is floor(R1 * 2^K * R2 / R3 * 10^6) .

solve(N,K,A):-
    (res(N,K,R)->(R==A->Str=" ok  ";Str=" no  ");
    write(fail)),write(" "),write(Str),writeln(R),!.

start:-f2(N,K,A),solve(N,K,A),fail.
start.

f2(2, 2,666666).
f2(4, 2,685714).
f2(5, 1,238095).
f2(13, 9,211187).
f2(30, 20,67130).
f2(41, 17,126481).
f2(80, 24,226).
f2(99, 47,137249).
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0