AtCoder Beginner Contest #011 D問題 - 大ジャンプ

Source

AtCoder Beginner Contest #011
問題文

問題概要

二次元平面上の $(a,b)$ にいるとき,$1$ 回ジャンプすると,等確率に $(a+D,b),\ (a-D,b),\ (a,b+D),\ (a,b-D)$ のどこかに移動する.
最初 $(0,0)$ にいて,ちょうど $N$ 回だけジャンプした後に,$(X,Y)$ にいる確率を求める問題.

解法

$X$ または $Y$ が $D$ で割り切れないならば,到達不可能なので答えは $0$.
$X$ と $Y$ を $D$ で割って,$D=1$ の時に帰着させる.
ジャンプして,$x$ 軸方向に動いた回数 $k$ を全て試す.このような確率は $\frac{N!}{k!(N-k)!} (\frac{1}{2})^N$ となる.
$k$ 回のうち,正の方向には $X + (k-X)/2$ 回,負の方向には $(k-X)/2$ 回ジャンプすれば良い.回数が非負整数でなければ不可能.
このような確率も,$\frac{a!}{b!(a-b)!} (\frac{1}{2})^a$ の形でかけ,$y$ 軸方向も同様に計算できる.
なので,条件を満たす確率を掛けあわせて,$k$ を動かしつつ足し合わせれば良い.
ただし,$P(a,b) = \frac{a!}{b!(a-b)!} (\frac{1}{2})^a$ をそのまま計算するとオーバーフローしてしまう可能性があるので,
$P(a,b)$ に対する漸化式(二項係数のパスカルの三角形の漸化式とほぼ似たような感じ)を用いてDPする,とか,$\log$ を取って計算する($\log (k!)$ を前計算しておく)などして対処する.
時間計算量 $O(N)$.$P(a,b)$ を漸化式で求めた場合は $O(N^2)$.

C++によるスパゲッティなソースコード

#include<bits/stdc++.h>
using namespace std;

#define REP(i,a,b) for(i=a;i<b;i++)
#define rep(i,n) REP(i,0,n)

#define mygc(c) (c)=getchar_unlocked()
void reader(int *x){int k,m=0;*x=0;for(;;){mygc(k);if(k=='-'){m=1;break;}if('0'<=k&&k<='9'){*x=k-'0';break;}}for(;;){mygc(k);if(k<'0'||k>'9')break;*x=(*x)*10+k-'0';}if(m)(*x)=-(*x);}
void reader(int *x, int *y){reader(x);reader(y);}

int N, D, X, Y;
double pw[1200], fact[1200];

double C(int a, int b){
  return exp( pw[a] + fact[a] - fact[a-b] - fact[b] );
}

double solve(int N, int X){
  int i, j;
  
  if(N < X || N%2 != X%2) return 0;

  i = X + (N-X)/2;
  j = (N-X)/2;

  return C(i+j, i);
}

int main(){
  int i, j, k;
  double res = 0;

  pw[0] = 0; fact[0] = 0;
  REP(i,1,1200) pw[i] = pw[i-1] + log(0.5);
  REP(i,1,1200) fact[i] = fact[i-1] + log(i);

  reader(&N,&D);
  reader(&X,&Y);


  if(X%D || Y%D){
    puts("0"); return 0;
  }

  X /= D;
  Y /= D;
  if(X < 0) X = -X;
  if(Y < 0) Y = -Y;

  rep(i,N+1) res += solve(i, X) * solve(N-i, Y) * C(N,i);
  printf("%.15f\n", res);

  return 0;
}

Current time: 2017年09月25日07時55分36秒
Last modified: 2014年06月26日21時38分46秒 (by laycrs)
Tags: Competitive_Programming AtCoder AtCoder_Beginner_Contest ABC011 ABC_D
トップページに戻る

Logged in as: unknown user (not login)

ログイン: