using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("2 10000000");
WillReturn.Add("10000000 10000000");
//0.125
}
else if (InputPattern == "Input2") {
WillReturn.Add("100 2");
WillReturn.Add("3 7");
//0.0
}
else if (InputPattern == "Input3") {
WillReturn.Add("11 8562174");
WillReturn.Add("25686522 17124348");
//0.018174648284912
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static void Main()
{
List<string> InputList = GetInputList();
decimal[] wkArr = { };
Action<string> SplitAct = pStr =>
wkArr = pStr.Split(' ').Select(pX => decimal.Parse(pX)).ToArray();
SplitAct(InputList[0]);
decimal N = wkArr[0];
decimal D = wkArr[1];
SplitAct(InputList[1]);
decimal X = wkArr[0];
decimal Y = wkArr[1];
if (X % D != 0 || Y % D != 0) {
Console.WriteLine(0M);
return;
}
X /= D;
Y /= D;
// ゴールはプラスにしておく
X = Math.Abs(X);
Y = Math.Abs(Y);
decimal Answer = 0M;
for (decimal I = 0; I <= N; I++) {
//X方向に移動する回数
decimal MoveXCnt = I;
//Y方向に移動する回数
decimal MoveYCnt = N - I;
bool CanMove1;
decimal PlusCnt1;
decimal MinusCnt1;
DeriveCanMove(X, MoveXCnt, out CanMove1, out PlusCnt1, out MinusCnt1);
bool CanMove2;
decimal PlusCnt2;
decimal MinusCnt2;
DeriveCanMove(Y, MoveYCnt, out CanMove2, out PlusCnt2, out MinusCnt2);
if (CanMove1 == false || CanMove2 == false) {
continue;
}
if (N < 30) {
decimal CurrProb = DeriveCombi(N, PlusCnt1);
CurrProb *= DeriveCombi(N - PlusCnt1, MinusCnt1);
CurrProb *= DeriveCombi(N - PlusCnt1 - MinusCnt1, PlusCnt2);
CurrProb *= (decimal)(Math.Pow(1D / 4D, (double)(N)));
Answer += CurrProb;
}
else {
double CurrProbLog10 = DeriveCombiLog10(N, PlusCnt1);
CurrProbLog10 += DeriveCombiLog10(N - PlusCnt1, MinusCnt1);
CurrProbLog10 += DeriveCombiLog10(N - PlusCnt1 - MinusCnt1, PlusCnt2);
CurrProbLog10 += (double)N * Math.Log10(1D / 4D);
Answer += (decimal)(Math.Pow(10, CurrProbLog10));
}
}
Console.WriteLine(Answer);
}
// 目標座標と移動回数を引数として、
// 到達可否とプラスの移動回数とマイナスの移動回数を返す
static void DeriveCanMove(decimal pGoalPos, decimal pMoveCnt,
out bool pCanMove, out decimal pPlusCnt, out decimal pMinusCnt)
{
pCanMove = true;
pPlusCnt = pGoalPos;
pMinusCnt = 0M;
// 移動回数が不足している場合
if (pMoveCnt < pGoalPos) {
pCanMove = false;
return;
}
decimal RestCnt = pMoveCnt - pGoalPos;
// 偶数でなかったらNG
if (RestCnt % 2 > 0) {
pCanMove = false;
return;
}
pPlusCnt += RestCnt / 2;
pMinusCnt += RestCnt / 2;
}
// nCrを求める
static decimal DeriveCombi(decimal pN, decimal pR)
{
decimal WillReturn = 1;
pR = Math.Min(pR, pN - pR);
var DivList = new List<decimal>();
for (decimal I = 2; I <= pR; I++) {
DivList.Add(I);
}
for (decimal I = pN - pR + 1; I <= pN; I++) {
WillReturn *= I;
for (int J = DivList.Count - 1; 0 <= J; J--) {
if (WillReturn % DivList[J] == 0) {
WillReturn /= DivList[J];
DivList.RemoveAt(J);
}
}
}
return WillReturn;
}
// nCrのLog10を求める
static double DeriveCombiLog10(decimal pN, decimal pR)
{
double WillReturn = 0;
pR = Math.Min(pR, pN - pR);
for (decimal I = 2; I <= pR; I++) {
WillReturn -= Math.Log10((double)I);
}
for (decimal I = pN - pR + 1; I <= pN; I++) {
WillReturn += Math.Log10((double)I);
}
return WillReturn;
}
}