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

public class Alex_PathCompression_Scanner{
	public static void main(String[] args) throws Exception {
		new Alex_PathCompression_Scanner().main();
	}

	// greatest common divisor
	long gcd(long a, long b){
		if(b != 0)return gcd(b, a % b);
		return a;
	}

	long x[];    // positions
	int next_[]; // next possible index after shooting on the current index and recharging
	int gNext[]; // next position to shoot at - for implementation of path compression
	boolean removed[]; // specifies whether this target is already eliminated

	int FUNCCALLS = 0; // just counts number of getNext-function calls - for debugging

	// getNext returns the id of the next target, which should be eliminated
	// it uses path compression
	int getNext(int n){
		++FUNCCALLS;
		if(removed[n]){
			return gNext[n] = getNext(gNext[n]);
		}
		return n;
	}

	int N, P, R;
	int main() {
		Scanner scan = new Scanner(System.in);
		N = scan.nextInt();
		P = scan.nextInt();
		R = scan.nextInt();
		x = new long[N];
		next_ = new int[N];
		gNext = new int[N];
		removed = new boolean[N];
		for(int i = 0; i < N; i++){
			x[i] = scan.nextInt();
		}
		Arrays.sort(x);
		// calculate next possible position if recharging
		long toGo = (R) % P;
		boolean fliped = false;
		for(int i = 0; i < N; i++){
			next_[i] = (i>0?next_[i-1]:1);
			if(!fliped){
				while(next_[i] < N && x[next_[i]] < x[i] + toGo)++next_[i];
			}
			if(next_[i] == N){
				next_[i] = 0;
				fliped = true;
			}
			if(fliped) {
				while(x[next_[i]] + P < x[i] + toGo)++next_[i];
			}
		}
		long MINDIST = (1L<<60);
		long MAXDIST = 0;
		long AVERAGE = 0;
		long RUNS = 0;

		// try all possible starts once
		long laststart = x[(int) N-1] - P;
		for(int j = 0; j < N; j++){
			if(x[j] != laststart){ // calculate values for current start if not already done
				// initialize removed and gNext
				for(int i = 0; i < N; i++) removed[i] = false;
				for(int i = 0; i < N; i++) gNext[i] = (i+1);
				gNext[N-1] = 0;
				long DIST = R; // represents the time since this test run has started
				// DIST is initially R as it counts storing the initial bag

				int cur = j; // current index
				removed[cur] = true; // initial target is destroyed
				for(int i = 1; i < N; i++) {
					int n = next_[cur]; // next possible index after recharging
					n = getNext(n); // next possible index which is not already removed
					// calculate the waiting time to shoot at the next target 
					long dist = x[n] - x[cur];
					toGo = R - dist;
					dist += ((toGo + P - 1) / P) * P; // do not forget the full cycles such recharging is finished
					// update distance and remove next object
					DIST += dist;
					cur = n;
					removed[n] = true;
				}
				// update result values
				long mult = x[j] - laststart;
				MINDIST = Math.min(MINDIST, DIST);
				MAXDIST = Math.max(MAXDIST, DIST + mult - 1);
				AVERAGE += DIST * mult;
				AVERAGE += (mult * (mult - 1)) / 2;
				RUNS += mult;
				laststart = x[j];
			}
		}
		long gc = gcd(AVERAGE, RUNS);
		AVERAGE /= gc;
		RUNS /= gc;
		System.out.println(MINDIST);
		System.out.println(MAXDIST);
		System.out.println(AVERAGE + "/" + RUNS);
		return 0;
	}
}
