AOJ0504 Card Game II

問題リンク Card Game II

  • 解法

公式解説を読んで解きましたが、所々理解が追いついてない状態です。
Mで場合分けして解くようです。
M=0のとき、nk枚目に引くカード(最後に引くカード)が1である場合が、ゲームをクリアする必要十分条件というらしいのです。そして、最後が1であれば、直前のkn-1枚のカードはどんな順列でも途中でカードの山が尽きてゲームオーバーになることがない、らしいです。これは自力では気づける自信がないなー・・・。結局、(最後が1であるような場合の数)/(全順列数)が答えの確率になります。実はこの確率は1/nになります(!)。
M=1のとき。1度もゲームオーバーになることなくクリアできる確率は上述の通り1/nになります。そして、(自分は数学力がからっぽなので)驚くべきことに、2回目の試行でクリアできる確率を求めるにはk=1の場合だけ考えれば十分らしいのです。M=0のときは、式の結果にkが入ってこないからkが答えに影響しないことが分かるのですが、M=1の場合でいきなりそんなこと言われても分からない・・・。まぁこれを信じることにすると、1が書かれたカードをi番目(1 <= i < n)に引く確率はそれぞれ1/n。残ったn-i枚で、M=0のときと同じ議論をすると、クリアする確率は1/(n-i)。よって、2回目でクリアする確率は(1/n){(1/1)+(1/2)+...+(1/(n-1))}。これに1回目で成功する確率を加えた1/nを足したものが答えになります。

数学力が足りなさすぎる!!!

  • ソース
import java.util.Scanner;

//Card Game II
public class AOJ0504 {

	int[] res, t;
	
	void add(int D){
		t[0] = 1/D;
		int R = 1%D, id = 1;
		while(id<t.length){
			R*=10;
			t[id++] = R/D;
			R%=D;
		}
		for(int i=t.length-1;i>0;i--){
			res[i]+=t[i];
			res[i-1]+=res[i]/10;
			res[i]%=10;
		}
		res[0]+=t[0];
	}
	
	void div(int n){
		t[0] = res[0]/n;
		int R = res[0]%n, id = 1;
		while(id<t.length){
			R = R*10 + res[id];
			t[id++] = R/n;
			R%=n;
		}
		for(int i=0;i<t.length;i++)res[i] = t[i];
	}
	
	void run(){
		Scanner sc = new Scanner(System.in);
		for(;;){
			int n = sc.nextInt(), k = sc.nextInt(), m = sc.nextInt(), r = sc.nextInt();
			if((n|k|m|r)==0)break;
			res = new int[r+10];
			t = new int[r+10];
			if(m==0){
				add(n);
			}
			else{
				for(int i=1;i<n;i++)add(i);
				div(n);
				add(n);
			}
			System.out.print(res[0]+".");
			for(int i=1;i<=r;i++)System.out.print(res[i]+(i==r?"\n":""));
		}
	}
	
	public static void main(String[] args) {
		new AOJ0504().run();
	}
}