Problem: Ron is a master of a ramen shop.

Recently, he has noticed some customers wait for a long time. This has been caused by lack of seats during lunch time. Customers loses their satisfaction if they waits for a long time, and even some of them will give up waiting and go away. For this reason, he has decided to increase seats in his shop. To determine how many seats are appropriate, he has asked you, an excellent programmer, to write a simulator of customer behavior.

Customers come to his shop in groups, each of which is associated with the following four parameters:

* Ti : when the group comes to the shop
* Pi : number of customers
* Wi : how long the group can wait for their seats
* Ei : how long the group takes for eating



The i-th group comes to the shop with Pi customers together at the time Ti . If Pi successive seats are available at that time, the group takes their seats immediately. Otherwise, they waits for such seats being available. When the group fails to take their seats within the time Wi (inclusive) from their coming and strictly before the closing time, they give up waiting and go away. In addition, if there are other groups waiting, the new group cannot take their seats until the earlier groups are taking seats or going away.

The shop has N counters numbered uniquely from 1 to N. The i-th counter has Ci seats. The group prefers “seats with a greater distance to the nearest group.” Precisely, the group takes their seats according to the criteria listed below. Here, SL denotes the number of successive empty seats on the left side of the group after their seating, and SR the number on the right side. SL and SR are considered to be infinity if there are no other customers on the left side and on the right side respectively.

1. Prefers seats maximizing min{SL, SR}.
2. If there are multiple alternatives meeting the first criterion, prefers seats maximizing max{SL, SR}.
3. If there are still multiple alternatives, prefers the counter of the smallest number.
4. If there are still multiple alternatives, prefers the leftmost seats.



When multiple groups are leaving the shop at the same time and some other group is waiting for available seats, seat assignment for the waiting group should be made after all the finished groups leave the shop.

Your task is to calculate the average satisfaction over customers. The satisfaction of a customer in the i-th group is given as follows:

* If the group goes away without eating, -1.
* Otherwise, (Wi - ti )/Wi where ti is the actual waiting time for the i-th group (the value ranges between 0 to 1 inclusive).



Input

The input consists of multiple datasets.

Each dataset has the following format:


N M T
C1 C2 ... CN
T1 P1 W1 E1
T2 P2 W2 E2
...
TM PM WM EM


N indicates the number of counters, M indicates the number of groups and T indicates the closing time. The shop always opens at the time 0. All input values are integers.

You can assume that 1 ≤ N ≤ 100, 1 ≤ M ≤ 10000, 1 ≤ T ≤ 109, 1 ≤ Ci ≤ 100, 0 ≤ T1 < T2 < ... < TM < T, 1 ≤ Pi ≤ max Ci, 1 ≤ Wi ≤ 109 and 1 ≤ Ei ≤ 109.

The input is terminated by a line with three zeros. This is not part of any datasets.

Output

For each dataset, output the average satisfaction over all customers in a line. Each output value may be printed with an arbitrary number of fractional digits, but may not contain an absolute error greater than 10-9.

Example

Input

1 4 100
7
10 1 50 50
15 2 50 50
25 1 50 50
35 3 50 50
1 2 100
5
30 3 20 50
40 4 40 50
1 2 100
5
49 3 20 50
60 4 50 30
1 2 100
5
50 3 20 50
60 4 50 30
2 3 100
4 2
10 4 20 20
30 2 20 20
40 4 20 20
0 0 0


Output

0.7428571428571429
0.4285714285714285
0.5542857142857143
-0.1428571428571428
0.8000000000000000

Solution (in CPP):

Solution:
#include<iostream>
#include<cassert>
#include<vector>
#include<map>
#include<cmath>
#include<algorithm>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define pb         push_back
#define ALL(C)    (C).begin(),(C).end()

typedef long long ll;

const int N = 100;
const int M = 10000;
const int dinf=20000;
const ll inf = (1LL)<<50;

class Seat{
public:
  int a,b;
  ll time;
  bool operator<(const Seat & t)const{
    return a < t.a;
  }
};

int ind,amax,amin,al,ar;

void update(int tindex,int l,int r,int posl,int posr){
  if (l > r)swap(l,r);
  
  if (ind==-1||
      (l>amin)||
      (l==amin&&r >amax)){
    //||(l==amin&&r==amax&&tindex < ind)||
    //(l==amin&&r==amax&&tindex==ind&&posl<al)){
    ind=tindex;
    amin=l;
    amax=r;
    al=posl;
    ar=posr;
  }
}

void makeupdate(int tindex,int b,int a,int cap,int req){
  int tmp = a-b-1;
  if (tmp < req)return;
  int val=tmp-req;
  int l,r;
  l=val/2;r=val/2;
//   if (tmp%2 == 1 && req%2 == 0){
//     r++;
//   }else if (tmp%2 == 0 && req%2 == 1){
//     r++;
//   }
  if (val%2 == 1)r++;
  update(tindex,l,r,b+1+l,a-1-r);
}

void check(int cap,vector<Seat> &info,int req,int tindex){
  if (info.size() == 0){
    if (req > cap)return;
    if(req-1<cap)update(tindex,dinf,dinf,0,req-1);
    return;
  }
  
  if (info[0].a >= req){
    update(tindex,dinf,info[0].a-req,0,req-1);
  }  

  rep(i,(int)info.size()-1){
    makeupdate(tindex,info[i].b,info[i+1].a,cap,req);
  }

  if (cap-info[info.size()-1].b-1 >=req){
    update(tindex,cap-req-info[info.size()-1].b-1,dinf,cap-req,cap-1);
  }
}

void getseat(int n,vector<Seat> *a,int *cap,int req){
  rep(i,n){
    if (cap[i]>=req)check(cap[i],a[i],req,i);
  }
}

double solve(int n,int *cap,ll cl,int m,ll *come,int *num,ll *wait,ll *eat){
  ll now=-1;
  int top=0;
  double sum=0,div=0;
  vector<Seat> seat[N];
  rep(i,m)div+=num[i];
  
  while(top < m){
    ll fast=inf;
    rep(i,n){
      rep(j,seat[i].size()){
	fast=min(fast,seat[i][j].time);
      }
    }
    
    if (now < come[top] && come[top] < fast){//arrive
      now=come[top];
    }else if (fast != inf && fast > come[top]+wait[top]){//leave from queue
      now=come[top]+wait[top];
      sum+=(-1)*num[top];
      top++;
    }else now = fast;////leave from seat
    
    //    cout << now <<" " << cl << endl;

    if (now >=cl)break;

    rep(i,n){
      for(int j=(int)seat[i].size()-1;j>=0;j--){
	if (seat[i][j].time <= now){
	  seat[i].erase(seat[i].begin()+j);
	}
      }
    }

//      rep(i,n){
//        rep(j,seat[i].size()){
//   	cout <<"seat info " <<i<<" " <<  seat[i][j].a <<" " << seat[i][j].b <<" " << seat[i][j].time<<endl;
//        }
//      }
       
    while(top < m){
      while(top<m){
	if (now > come[top]+wait[top]){
	  sum+=(-1)*num[top];
	}else break;
	top++;
      }
      
      if (top == m || now < come[top])break;
      
      ind=-1;
      getseat(n,seat,cap,num[top]);
      if (ind == -1)break;
      
      seat[ind].pb((Seat){al,ar,now+eat[top]});
      //      cout << top <<" can sit " << ind <<" " << al <<" " << ar <<" "<<
      //	now <<" " << now+eat[top] <<  endl;
      sort(ALL(seat[ind]));
      sum+=((wait[top]-(now-come[top]))/(double)wait[top])*num[top];
      top++;
    }
  }
  REP(i,top,m)sum+=(-1)*num[i];
  return sum/div;
}

int main(){
  int n,m;
  ll t;
  int cap[N];
  int num[M];
  ll come[M],wait[M],eat[M];
  while(cin>>n>>m>>t && n){
    rep(i,n)cin>>cap[i];
    rep(i,m)cin>>come[i]>>num[i]>>wait[i]>>eat[i];
    printf("%.16lf\n",solve(n,cap,t,m,come,num,wait,eat));
  }
  return false;
}


/*
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
0 0 0 x x x 4 4 4 7  7  7     2  2  2  8  8  8     3  3  3  9  9  9     1  1  1  
*/