>原です。
>
>明日は休日なので、次の問題を解きなさい。
>
>  次の条件を満たすようなサイコロの組を求めよ。ただしサイコロの各面
>  の出る確率は等しく、違う面に同じ数字が重複して書かれていてもよい。
>  
>  (1) サイコロは A, B, C, D の 4 つ。
>  (2) サイコロは 6 面体。
>  (3) 書かれる数字は 0 から 6 まで。
>  (4) 異なるサイコロには異なる数字が書かれている。(引き分けがない)
>  (5) 巡回的な強さをもつ。(つまり、X が Y に勝つ確率を p(X, Y) とす
>    ると、p(A, B) = p(B, C) = p(C, D) = p(D, A) < 1/2)

近岡です。
僭越ながら解答を載せます。

帰宅時、車を運転しながらプログラムを考えていました。
多重ループで処理することにして、枝をかる条件を考えていると、
いつの間にか解が求まってしまいました。
その思考過程をプログラムにしようと思って四苦八苦したわけですが、
うまくいかず、結局、多重ループをまわしています。

条件(2)で6面体の形状は指定されていないので、
どの面に何番が書かれているかまで考慮する意味はありません。

条件(4)は、言い換えると「同じ番号が複数のさいころに書かれることはない」と
いうことですから、条件(1)(3)とディリクレの引き出し論法(鳩ノ巣論法)により、
ABCDのいずれか少なくとも1つは、全ての面が同じ番号です。
簡単な場合わけから、全ての面が同じ番号のさいころが複数ないことがわかりますから、
「さいころAのみ全ての面が同じ番号。他のさいころは2種類の番号が書かれている」
と仮定してかまいません。

さらにプログラム中では
「サイコロB,C,Dの大きいほうの目がAの目より大きく、
  サイコロB,C,Dの小さいほうの目がAの目より小さい」
という条件を仮定しています。この条件はかなり強力です。
# 条件(5)式「p(A, B) = p(B, C) = p(C, D) = p(D, A) < 1/2」の
# 最後の「 < 1/2 」がなければ、こんな条件は成り立たないのですが。

サイコロA 6面とも3
サイコロB 2面が6、4面が2
サイコロC 3面が5、3面が1
サイコロD 4面が4、2面が0

# 今、気がついたのですが、p(X,Y)を「XがYに勝つ確率」ではなくて、
# 「YがXに勝つ確率」にして解いています。
# 訂正は後日ということで勘弁を。

==== プログラムはここから ====
A = []; B = []; C = []; D = []
Set = []

def prob2(k , dice)
  tmp = 0
  dice.each { |pair|
    tmp += pair[1] if k<pair[0]
  }
  tmp
end

def prob(dice1, dice2)
  # サイコロdice2がサイコロdice1に勝つ確率
  tmp=0
  dice1.each { |pair|
    tmp += pair[1]*prob2(pair[0], dice2);
  }
  tmp
end

def loop_d(n,m,a)
  # h>l サイコロDの目
  for h in (a+1)..6 do
    next if Set[h];
    for l in 0..(a-1) do
      next if Set[l];
      D[0..-1] = [[h,6-n],[l,n]]
      next if prob(C,D) != 6*n
      Set[h]=Set[l]=1;
      p ["A=",A,"B=",B,"C=",C,"D=",D]
      Set[h]=Set[l]=nil;
    end
  end
end
  
def loop_c(n,m,a)
  # h>l サイコロCの目
  for h in (a+1)..6 do
    next if Set[h];
    for l in 0..(a-1) do
      next if Set[l];
      C[0..-1] = [[h,m],[l,6-m]]
      next if prob(B,C) != 6*n
      Set[h]=Set[l]=1;
      loop_d(n,m,a)
      Set[h]=Set[l]=nil;
    end
  end
end

def loop_b(n,m,a)
  # h>l サイコロBの目
  for h in (a+1)..6 do
    next if Set[h];
    for l in 0..(a-1) do
      next if Set[l];
      B[0..-1] = [[h,n],[l,6-n]]
      Set[h]=Set[l]=1
      loop_c(n,m,a)
      Set[h]=Set[l]=nil
    end
  end
end

def loop_a(n,m)
  # a サイコロAの目
  for a in 1..5 do
    next unless (6-a)>=3 and (a-0)>=3
    A[0..-1] = [[a,6]]
    Set[a]=1;
    loop_b(n,m,a)
    Set[a]=nil;
  end
end

def loop_n()
  for n in (1..2) do
    n0=6-n ; # n は B の大きいほうの目の個数
    for m in (1..5) do 
      m0=6-m # m は C の大きいほうの目の個数
      next unless [n0*m,  6*m,  6*n0, 36-n*m0].index(6*n)
      # C が B に勝つ確率が(6*n)/36になりえない場合は除く
      next unless [n0*m0, 6*n0, 6*m0, 36-n*m ].index(6*n)
      # D が C に勝つ確率が(6*n)/36になりえない場合は除く
      # 頭の中で考えたときは、ここは、素因数分解などを使って
      # 余分な枝を全て刈っていたのですが…
      loop_a(n,m)
    end
  end
end

loop_n()

0----+----1----+----2----+----3----+----4----+----5----+----6
近岡 宣吉  Chikaoka, Nobuyoshi
富山県立高岡西高等学校(数楽科)
 E-mail : chikaoka-nobuyoshi / tym.ed.jp