湖南2020多校对抗赛round1 NWERC2014
湖南2020多校对抗赛round1 NWERC2014
题目来源:http://codeforces.com/gym/101482
题号 | 赛中 | 赛后 | |
---|---|---|---|
A | Around the Track | × | |
B | Biking Duck | × | |
C | Cent Savings | √ | |
D | Digi Comp II | √ | |
E | Euclidean TSP | √ | |
F | Finding Lines | √ | |
G | Gathering | × | |
H | Hyacinth | √ | |
I | Indoorienteering | × | |
J | Judging Troubles | √ | |
K | Knapsack Collection | × | √ |
C(动态规划):
题意:
给了你n个物品,每个物品的价值为pi,你最多可以将这n个物品分成d+1堆来购买这些物品,购买物品的规则是这样的,如果一堆物品的总价值为sum,那么购买这一堆物品的费用为sum的四舍五入的值,假设这一堆物品价值为126,那么购买他就需要130,假设这一堆物品价值为124,那么购买他就需要120元
求,购买这n个物品最少花费多少钱
题解:
\(dp[i][j]表示前i堆分成j堆最少需要花费多少钱\)
\(边界:dp[i][1]=getval(sum[i])\)
\(转移:dp[k][j] = min(dp[k][j], dp[i][j - 1] + getval(sum[k] - sum[i]));\)
\(时间复杂度:O(d*n^2)\)
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <bitset>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
#define debug4(x,y,z,m) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]"<<" ["<<#m<<" "<<m<<"]\n"
const int maxn = 2e3 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double Pi = acos(-1);
LL gcd(LL a, LL b) {
return b ? gcd(b, a % b) : a;
}
LL lcm(LL a, LL b) {
return a / gcd(a, b) * b;
}
double dpow(double a, LL b) {
double ans = 1.0;
while(b) {
if(b % 2)ans = ans * a;
a = a * a;
b /= 2;
} return ans;
}
LL quick_pow(LL x, LL y) {
LL ans = 1;
while(y) {
if(y & 1) {
ans = ans * x % mod;
} x = x * x % mod;
y >>= 1;
} return ans;
}
int dp[maxn][30];
int a[maxn];
int sum[maxn];
int getval(int val) {
if(val % 10 >= 5) {
return val - val % 10 + 10;
} else {
return val - val % 10;
}
}
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
int n, d;
scanf("%d%d", &n, &d);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
sum[i] = sum[i - 1] + a[i];
}
memset(dp, INF, sizeof(dp));
for(int i = 1; i <= n; i++) {
dp[i][1] = getval(sum[i]);
// debug1(dp[i][1]);
}
for(int i = 1; i <= n; i++) {
for(int j = 2; j <= d + 1; j++) {
for(int k = i + 1; k <= n; k++) {
dp[k][j] = min(dp[k][j], dp[i][j - 1] + getval(sum[k] - sum[i]));
// debug3(i, j, k);
// debug3(dp[k][i], dp[i][j - 1], getval(sum[k] - sum[i - 1]));
}
}
}
int ans = INF;
for(int i = 1; i <= d + 1; i++) {
// debug1 (dp[n][i]);
ans = min(dp[n][i], ans);
}
printf("%d\n", ans);
return 0;
}
cwolf9定义状态是
前i堆最多可以节省多少钱
int n, m, k;
int dp[MXN][21], ar[MXN], pre[MXN];
int check(int a, int b) {
int x = (pre[b]-pre[a]) % 10;
int y = pre[b]-pre[a] - x;
return (x>=5?x-10:x);
}
int main() {
#ifndef ONLINE_JUDGE
// freopen("D:\\in.in", "r", stdin);
// freopen("D:\\out.out", "w", stdout);
#endif
n = read();
m = read() + 1;
for(int i = 1; i <= n; ++i) ar[i] = read(), pre[i] = pre[i-1] + ar[i];
for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) dp[i][j] = - INF;
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= min(m, i); ++j) {
for(int k = 0; k < i; ++k) {
if(j == 1 && k > 0) continue;
if(k >= j - 1) {
dp[i][j] = max(dp[i][j], dp[k][j-1] + check(k, i));
}
}
}
}
int ans = INF;
// printf("%d\n", pre[n]);
for(int i = 1; i <= m; ++i) {
ans = min(ans, pre[n] - dp[n][i]);
// printf("%d\n", dp[n][i]);
}
printf("%d\n", ans);
#ifndef ONLINE_JUDGE
cout << "time cost:" << 1.0 * clock() / CLOCKS_PER_SEC << "ms" << endl;
system("pause");
#endif
return 0;
}
D(拓扑排序):
题意:
有m个传送门,传送门分左右两边,每个传送门初始时都有一个状态“L”或者"R",现在有n个小球从1号节点出发,每到一个传送门就会被传送到传送门当前状态指向的节点,每次传送门传送完一个小球后就会将当前状态反转,保证可以到达终点0,问m个传送门最后的状态是怎么样的
题解:
可以解得,如果传送门被经过了奇数次,那么传送门的状态就会反转,否则传送门就不会改变状态,所以拓扑排序一遍后记录每个传送门被经过的次数就行了
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <bitset>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 5e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double Pi = acos(-1);
LL gcd(LL a, LL b) {
return b ? gcd(b, a % b) : a;
}
LL lcm(LL a, LL b) {
return a / gcd(a, b) * b;
}
double dpow(double a, LL b) {
double ans = 1.0;
while(b) {
if(b % 2)ans = ans * a;
a = a * a;
b /= 2;
} return ans;
}
LL quick_pow(LL x, LL y) {
LL ans = 1;
while(y) {
if(y & 1) {
ans = ans * x % mod;
} x = x * x % mod;
y >>= 1;
} return ans;
}
struct node {
int l, r;
char sta[3];
} a[maxn];
int vis[maxn];
int in[maxn];
LL num[maxn];
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
LL n;
int m;
scanf("%lld%d", &n, &m);
for(int i = 1; i <= m; i++) {
scanf("%s %d %d", a[i].sta, &a[i].l, &a[i].r);
in[a[i].l]++;
in[a[i].r]++;
}
queue<int> q;
num[1] = n;
for(int i = 1; i <= m; i++) {
if(in[i] == 0) {
q.push(i);
}
}
while(!q.empty()) {
int u = q.front();
q.pop();
if(num[u] % 2 == 1) vis[u] = 1;
if(a[u].sta[0] == 'L') {
num[a[u].l] += (num[u] - num[u] / 2);
num[a[u].r] += num[u] / 2;
} else {
num[a[u].r] += (num[u] - num[u] / 2);
num[a[u].l] += num[u] / 2;
}
in[a[u].l]--;
if(in[a[u].l] == 0) {
q.push(a[u].l);
}
in[a[u].r]--;
if(in[a[u].r] == 0) {
q.push(a[u].r);
}
}
for(int i = 1; i <= m; i++) {
if(vis[i] == 1) {
if(a[i].sta[0] == 'L') {
a[i].sta[0] = 'R';
} else {
a[i].sta[0] = 'L';
}
}
}
for(int i = 1; i <= m; i++) {
printf("%c", a[i].sta[0]);
}
printf("\n");
return 0;
}
E(三分):
题意:
根据题目给的公式和例可以猜出来time t=第二个公式的值和第三个公式的值
然后再反过去读题就知道
\((n * pow(log2(n), c * sqrt(2))) / (p * 1e9);\)
\(s * (1 + 1.0 / c) / v;\)
分别是题目给你的两个公式,第一个公式是一个关于c递增的公式,第二个公式是一个关于c递减的公式
那么时间的最小值是根据c来的,我们需要找到波谷
所以这里就可以想到是三分求波谷了
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <bitset>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 3e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double Pi = acos(-1);
LL gcd(LL a, LL b) {
return b ? gcd(b, a % b) : a;
}
LL lcm(LL a, LL b) {
return a / gcd(a, b) * b;
}
double dpow(double a, LL b) {
double ans = 1.0;
while(b) {
if(b % 2)ans = ans * a;
a = a * a;
b /= 2;
} return ans;
}
LL quick_pow(LL x, LL y) {
LL ans = 1;
while(y) {
if(y & 1) {
ans = ans * x % mod;
} x = x * x % mod;
y >>= 1;
} return ans;
}
int n, m, k;
double p, s, v, c, t;
double first(double c) {
return n * pow(log(n), c * sqrt(2));
}
double second(double c) {
return (n * pow(log2(n), c * sqrt(2))) / (p * 1e9);
}
double third(double c) {
return s * (1 + 1.0 / c) / v;
}
double get(double c) {
return second(c) + third(c);
}
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
cin >> n >> p >> s >> v;
double l = 0, r = 100, ans = 1e18, c;
int T = 100;
while(T--) {
double lmid = l + (r - l) / 3.0;
double rmid = r - (r - l) / 3.0;
double Lans = get(lmid), Rans = get(rmid);
if(Rans > Lans) {
r = rmid;
if(ans > Lans) ans = Lans, c = lmid;
} else {
l = lmid;
if(ans > Rans) ans = Rans, c = rmid;
}
}
printf("%.9f %.9f\n", ans, c);
return 0;
}
F(随机):
题意:
平面上有n个点,问是否存在[n · p/100]向上取整个点在同一条直线上面
随机大法
证明如下:
#include <bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define x first
#define y second
#define rep(i,a,b) for(int i=a;i<b;++i)
#define per(i,a,b) for(int i=a-1;i>=b;--i)
#define fuck(x) cout<<'['<<#x<<' '<<(x)<<']'
#define eps 1e-8
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int ui;
typedef pair<int, int> PII;
const int MX = 1e6;
const int MM = 1e4;
namespace random {
typedef unsigned ui;
typedef long long ll;
typedef unsigned long long ull;
ui X, Y, Z, W; string str;
char in[15], ou[15];
void start() {
srand ( (ui) time (NULL) );
X = rand(), Y = X ^ rand(), Z = Y ^ rand();
}
ui RNG61() {
X = X ^ (X << 11);
X = X ^ (X >> 4);
X = X ^ (X << 5);
X = X ^ (X >> 14);
W = X ^ Y ^ Z;
X = Y;
Y = Z;
Z = W;
return Z;
}
int Randint (int mod) {
return RNG61() % mod + 1;
}
ll Randll(ll mod) {
return ((ull)RNG61() << 32 | RNG61()) % mod + 1;
}
double Randdouble(int l, int r) {
if(l == r) return l;
if(l > r) swap(l, r);
double ret = RNG61() % (r - l) + l;
double tmp = RNG61();
while(tmp > 1) tmp /= 10;
ret += tmp;
return ret;
}
}
const int maxn = 1e5 + 5;
struct Point {
int x, y;
} a[maxn];
bool check(Point t1, Point t2, Point t3) {
int x1 = t1.x;
int x2 = t2.x;
int x3 = t3.x;
int y1 = t1.y;
int y2 = t2.y;
int y3 = t3.y;
if((y2 - y1) * (x3 - x2) == (y3 - y2) * (x2 - x1)) {
return true;
}
return false;
}
using namespace random;
int main() {
int n, p;
scanf("%d%d", &n, &p);
for(int i = 1; i <= n; i++) {
scanf("%d%d", &a[i].x, &a[i].y);
}
int num = (n * p + 99) / 100;
start();
int T = 1000;
int flag = 0;
while(T--) {
int x = Randint(n);
int y = Randint(n);
if(x == y) {
y = x + 1;
}
Point t1 = a[x];
Point t2 = a[y];
int cnt = 0;
for(int i = 1; i <= n; i++) {
if(check(t1, t2, a[i])) {
cnt++;
}
}
if(cnt >= num) {
flag = 1;
}
}
if(flag) {
printf("possible\n");
} else {
printf("impossible\n");
}
}
H(贪心+dfs):
题意:
每个节点可以有一段波分的频率
如果两个相邻的节点有相同的频率,那么就可以使用其中的一个频率通信
现在给你一颗n个节点形成的树,现在让你给每个节点构造一段他自己的频率,使得,总的在使用中的频率个数最多,并且每个相邻的节点都要可以通信
题解:
要想在使用中的节点最多,那么每个频率至少用一次,假设a节点用了这个频率,那么他的所有儿子节点都要用上这个频率,可以先构造根节点的频率为【1 ,2】,然后从根节点往下走给每个子节点赋值和新建频率即可,这样可以保证在使用中的频率个数一定是最高的
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <bitset>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 3e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double Pi = acos(-1);
LL gcd(LL a, LL b) {
return b ? gcd(b, a % b) : a;
}
LL lcm(LL a, LL b) {
return a / gcd(a, b) * b;
}
double dpow(double a, LL b) {
double ans = 1.0;
while(b) {
if(b % 2)ans = ans * a;
a = a * a;
b /= 2;
} return ans;
}
LL quick_pow(LL x, LL y) {
LL ans = 1;
while(y) {
if(y & 1) {
ans = ans * x % mod;
} x = x * x % mod;
y >>= 1;
} return ans;
}
struct EDGE {
int v, nxt;
} edge[maxn << 1];
int head[maxn], tot;
void init() {
memset(head, -1, sizeof(head));
tot = 0;
}
void add_edge(int u, int v) {
edge[tot].v = v;
edge[tot].nxt = head[u];
head[u] = tot++;
}
struct node {
int x, y;
} a[maxn];
int in[maxn];
int vis[maxn];
int cnt = 2;
void dfs(int u, int fa) {
if(u == 1) {
for(int i = head[u]; i != -1; i = edge[i].nxt) {
int v = edge[i].v;
if(v == fa) continue;
dfs(v, u);
}
} else {
if(in[u] == 1 && u != 1) {
a[u].x = a[fa].x;
a[u].y = a[fa].y;
vis[a[u].x]++;
vis[a[u].y]++;
return;
}
if(vis[a[fa].x] >= 2) {
a[u].x = a[fa].y;
} else {
a[u].x = a[fa].x;
}
a[u].y = ++cnt;
vis[a[u].x]++;
vis[a[u].y]++;
for(int i = head[u]; i != -1; i = edge[i].nxt) {
int v = edge[i].v;
if(v == fa) continue;
dfs(v, u);
}
}
}
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
int n;
scanf("%d", &n);
init();
for(int i = 1, u, v; i < n; i++) {
scanf("%d%d", &u, &v);
add_edge(u, v);
add_edge(v, u);
in[u]++;
in[v]++;
}
a[1].x = 1;
a[1].y = 2;
vis[a[1].x]++;
vis[a[1].y]++;
cnt = 2;
dfs(1, 0);
for(int i = 1; i <= n; i++) {
printf("%d %d\n", a[i].x, a[i].y);
}
return 0;
}
J(签到):
题意:
你有n份代码提交到两个评测鸡上面,顺序并不确定,问两个评测鸡最多有多少份代码的评测结果是一样的
题解:
存一下评测结果然后加一下就行
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <bitset>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 3e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double Pi = acos(-1);
LL gcd(LL a, LL b) {
return b ? gcd(b, a % b) : a;
}
LL lcm(LL a, LL b) {
return a / gcd(a, b) * b;
}
double dpow(double a, LL b) {
double ans = 1.0;
while(b) {
if(b % 2)ans = ans * a;
a = a * a;
b /= 2;
} return ans;
}
LL quick_pow(LL x, LL y) {
LL ans = 1;
while(y) {
if(y & 1) {
ans = ans * x % mod;
} x = x * x % mod;
y >>= 1;
} return ans;
}
map<string, int>mp1, mp2;
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
string str;
cin >> str;
mp1[str]++;
}
for(int i = 1; i <= n; i++) {
string str;
cin >> str;
mp2[str]++;
}
map<string, int>::iterator it;
int ans = 0;
for(it = mp1.begin(); it != mp1.end(); it++) {
ans += min(mp1[it->first], mp2[it->first]);
}
printf("%d\n", ans);
return 0;
}
K(找规律+模拟):
题意:
有一个长度为s的圆形轮盘,有s个槽位,有n个行李箱在这些槽位上分布着,你可以站着某个槽位前取行李,取一个行李需要你花费t 的时间,每次只能取一个行李,轮盘每秒钟走一个单位长度,s-1和0的位置是连着的,问你取完所有的行李花费的最小时间、最大时间、平均时间是多少。
题解:
因为位置s特别大,可以对于每一个位置花费的总的时间打一个表,可以发现,如果原来的位置t上面有行李,而位置t+1上面没有行李的话,花费的时间是递减的,也就是说我们计算平均时间可以用到等差数列,因为n只有2000,所以我们可以对于每一个行李的位置都计算一遍时间,这样就可以知道所有位置的时间了
代码:
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <bitset>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 3e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double Pi = acos(-1);
LL gcd(LL a, LL b) {
return b ? gcd(b, a % b) : a;
}
LL lcm(LL a, LL b) {
return a / gcd(a, b) * b;
}
double dpow(double a, LL b) {
double ans = 1.0;
while(b) {
if(b % 2)ans = ans * a;
a = a * a;
b /= 2;
} return ans;
}
LL quick_pow(LL x, LL y) {
LL ans = 1;
while(y) {
if(y & 1) {
ans = ans * x % mod;
} x = x * x % mod;
y >>= 1;
} return ans;
}
int a[maxn];
int n, s, t;
LL tim[maxn];
LL cal(int x) {
LL ret = 0; int p = x;
multiset<int> st;
multiset<int>::iterator it;
for(int i = 1; i <= n; ++i) st.insert(a[i]);
while(!st.empty()) {
it = st.lower_bound(p);
if(it == st.end()) {
ret += s - p;
p = 0;
it = st.lower_bound(p);
}
ret += (*it) - p + t;
p = ((*it) + t) % s;
st.erase(it);
}
return ret;
}
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
scanf("%d%d%d", &n, &s, &t);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
sort(a + 1, a + 1 + n);
a[0] = -2;
LL sum = 0;
for(int i = 1; i <= n; ++i) {
if(a[i] == a[i - 1]) tim[i] = tim[i - 1];
else {
tim[i] = cal(a[i]);
}
}
LL mn = tim[1], mx = tim[1];
for(int i = 2; i <= n; ++i) {
mn = min(mn, tim[i]);
mx = max(mx, tim[i]);
}
for(int i = 1; i <= n; ++i) {
if(a[i] == a[i - 1]) continue;
int l = a[i - 1] + 1, r = a[i];
if(l == -1) l = a[n] + 1, r += s;
int len = r - l + 1;
mx = max(mx, tim[i] + len - 1);
sum += 1ll * (tim[i] + tim[i] + len - 1) * len / 2;
}
cout << mn << endl;
cout << mx << endl;
LL gcd = __gcd(sum, 1ll * s);
sum /= gcd;
s /= gcd;
cout << sum << '/' << s << endl; return 0;
}