Problem:
Problem C: Time Manipulation

彼女は見習いの魔法使いだ。
彼女はまず最初に時間を操る魔法を覚えた。
そして彼女は生計を立たせるために酒屋を開くことにした。
彼女の住んでいる国の住人達はみんなお酒が大好き、ということが関係している。
住人達は長い年数をかけて熟成させたお酒が特に好きで、熟成させた年数に応じてその価値も比例して上がる。
50年熟成させたお酒より100年熟成させたお酒のほうが価値が高いのは簡単に想像がつくはずだ。
そして手に入れるのが難しいということも。
彼女は自分の魔法を使って、長い年月熟成させたお酒を一瞬で作って、それを売って収入を得ようとしているのであった。

彼女はお酒を熟成させる年数に応じて値段を決めた。
例えば5年の熟成が必要なら5エメル、100年の熟成なら100エメルを払ってもらうことにした。
彼女にとってはどちらを作るのも同じ魔法を使うだけなので差は無い。
長い年数の熟成の注文の方が彼女にとっては得なのである。

彼女はまだ未熟なので今使える魔法には制約が2つある。
お酒をn 年より長く熟成させることは今の彼女には出来ない。
またm 個の整数が存在して、それらとその倍数の年数だけお酒を熟成させることも彼女には無理なのだ。

彼女は酒屋の経営だけ生活が出来るか不安に思っている。
どのくらいの収入を得ることが出来るか彼女には予想できない。
そこで1日の収入の期待値をもとにして、他の仕事をする必要があるかの判断を行うことにした。
幸い彼女は、野菜の栽培、ペットの世話、料理、裁縫、大工仕事など何でもできるので、酒屋での収入が少なくても困ることは無さそうだ。

彼女の1日の収入の期待値を計算するのがあなたの仕事だ。
なお期待値を計算する際に以下の3つを仮定してよい。

1日に引き受ける注文は必ず1つである。
住人は彼女に作れない年数のお酒は注文はしてこない。
住人の注文の年数は一様に分布している。

Input

入力は複数のケースからなる。
各ケースは以下のフォーマットで与えられる。

n m
p0 ... pm-1

住人は1 以上n 以下の整数の値の年数だけ熟成させたお酒を依頼してくる。

ただしm個の整数pi とその倍数を依頼してくる人はいない。

入力の終わりはn = 0 かつm =0 で与えられる。

各値は以下の条件を満たす

2 ≤ n ≤ 2,000,000,000

1 ≤ m ≤ 20

またpi はn を割り切ることが保証されている。

テストケースの数は200以下を超えない。

Output

彼女の一日の収入の期待値を出力せよ。

住人の注文として可能な年数が一つも存在しない場合は0を答えの期待値として出力せよ。

ジャッジが用意した正解の値と1e-5以下の誤差までが正答として許容される。

Sample input

12 3
2 3 6
12 4
1 2 3 6
0 0

Sample output

6.0000000000
0.0000000000

The University of Aizu Programming Contest 2011 Summer

原案、問題文: Tomoya Sakai

Solution in JAVA (judge verdict: Accepted)

import java.util.*;
import java.lang.*;
import java.math.*;
import java.io.*;

import static java.lang.Math.*;
import static java.util.Arrays.*;

// Time Manipulation
// 2012/12/04
public class Main{
	Scanner sc=new Scanner(System.in);

	void run(){
		for(;;){
			long n=sc.nextLong();
			int m=sc.nextInt();
			if((n|m)==0){
				break;
			}
			long[] p=new long[m];
			for(int i=0; i<m; i++){
				p[i]=sc.nextLong();
			}
			long sum=0;
			long num=0;
			for(int i=1; i<1<<m; i++){
				int bit=Integer.bitCount(i);
				long lcm=1;
				for(int k=0; k<m; k++){
					if((i>>k&1)==1){
						lcm=lcm/gcd(lcm, p[k])*p[k];
						if(lcm>n){
							break;
						}
					}
				}
				if(bit%2==0){
					num-=n/lcm;
					sum-=lcm*(n/lcm+1)*(n/lcm)/2;
				}else{
					num+=n/lcm;
					sum+=lcm*(n/lcm+1)*(n/lcm)/2;
				}
			}
			long a=n*(n+1)/2-sum;
			long b=n-num;
			if(b==0){
				println("0");
			}else{
				println(String.format("%.10f", (double)a/b));
			}
		}
	}

	long gcd(long m, long n){
		return m==0?n:gcd(n%m, m);
	}

	void println(String s){
		System.out.println(s);
	}

	public static void main(String[] args){
		new Main().run();
	}
}