Problem:
Enumeration

n個の整数a1, a2, …, anとn個の整数p1, p2, …, pn、整数mが与えられる。k番目の整数akをpk[%]の確率で選ぶ、という操作を各k(1 ≤ k ≤ n)について行い、0個以上n個以下の整数を選び出す。1以上m以下の整数の中で、選ばれた整数の少なくとも1つで割り切れるものの個数の期待値を求めよ。

Input

入力は以下の形式で与えられる。

n m
a1 a2 … an
p1 p2 … pn

Constraints

1 ≤ n ≤ 20

1 ≤ m ≤ 1018

1 ≤ ak ≤ 1018 (1 ≤ k ≤ n)

1 ≤ pk ≤ 99 (1 ≤ k ≤ n)

Output

問題の解を1行に出力せよ。出力には絶対誤差あるいは相対誤差で0.0000001(= 10-7)を超える誤差があってはならない。

Sample Input 1

2 15
3 5
50 50

Output for the Sample Input 1

3.75

確率

選ばれた数字

割り切る数

個数

25%

[]

 

0個

25%

[3]

3 6 9 12 15

5個

25%

[5]

5 10 15

3個

25%

[3,5]

3 5 6 9 10 12 15

7個

よって0.25 × (0 + 5 + 3 + 7) = 3.75

Sample Input 2

4 100
2 3 5 7
80 60 40 20

Output for the Sample Input 2

57.352

Sample Input 3

4 210
2 3 5 7
80 60 40 20

Output for the Sample Input 3

119.9136

Solution in C++11 (judge verdict: Memory Limit Exceeded)

#include <stdio.h>
#include <string.h>

#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define REP(i,b) FOR(i,0,(b))

typedef unsigned long long ull;
	
double dp[1<<20][20];

inline ull gcd(ull a,ull b){
	return b?gcd(b,a%b):a;
}

ull a[20];
int p[20];
int main(){
	int n;
	ull m;
	scanf("%d%llu",&n,&m);
	REP(i,1<<n)
		REP(j,n)
			dp[i][j]=0;
	REP(i,n)
		scanf("%llu",a+i);
	REP(i,n)
		scanf("%d",p+i);
	FOR(i,1,1<<n){
		int c=0;
		REP(j,n) c+=(i>>j)&1;
		REP(j,n)
			REP(k,c-1)
				dp[i][k]+=dp[i^(1<<j)][k];
		REP(k,c-1)
			dp[i][k]/=(c-1-k);
		ull s=1;
		REP(j,n)
			if((1<<j)&i){
				ull g=s>a[j]?gcd(s,a[j]):gcd(a[j],s);
				s/=g;
				if(s>m/a[j]){
					s=0;
					break;
				}else
					s*=a[j];
			}
		if(s)
			dp[i][c-1]=m/s;
	}
	double s=0;
	FOR(i,1,1<<n){
		double e=1;
		REP(j,n)
			if((1<<j)&i)
				e*=0.01*p[j];
			else
				e*=0.01*(100-p[j]);
		double f=0;
		int k=1;
		REP(j,n){
			f+=dp[i][j]*k;
			k=-k;
		}
		s+=f*e;
	}
	printf("%.8f\n",s);
}