第K小分数(二分)

第K小分数(二分)

Time limit:10000 ms
Memory limit:262144 kB
OS:Linux
Source:[Offer收割]编程练习赛46
judge:HihoCoder - 1692

描述

给定 N N N 个不同的质数 P 1 , P 2 , . . . , P N P_1, P_2, ... ,P_N P1,P2,...,PN 。用它们作为分目可以组成 ( P 1 − 1 ) + ( P 2 − 1 ) + . . . ( P N − 1 ) (P_1-1) + (P_2-1) + ... (P_N-1) (P11)+(P21)+...(PN1) 个分数:

1 P 1 , 2 P 1 , 3 P 1 , . . . , P 1 − 1 P 1 , \frac{1}{P_1}, \frac{2}{P_1}, \frac{3}{P_1}, ..., \frac{P_1-1}{P_1}, P11,P12,P13,...,P1P11,
1 P 2 , 2 P 2 , 3 P 2 , . . . , P 2 − 1 P 2 , \frac{1}{P_2}, \frac{2}{P_2}, \frac{3}{P_2}, ... ,\frac{P_2-1}{P_2}, P21,P22,P23,...,P2P21,
. . .   , ...\ , ... ,
1 P N , 2 P N , . . . , P N − 1 P N \frac{1}{P_N}, \frac{2}{P_N}, ... ,\frac{P_N-1}{P_N} PN1,PN2,...,PNPN1

请帮助小Ho求出其中第 K K K 小的分数。

Input

第一行包含两个整数 N N N K K K

以下 N N N 行每行包含一个质数 P i P_i Pi

对于 70 % 70\% 70% 的数据, 1 ≤ N ≤ 100 , 1 ≤ K ≤ 1000000 , 2 ≤ P i ≤ 100000 1 ≤ N ≤ 100, 1 ≤ K ≤ 1000000, 2 ≤ P_i ≤ 100000 1N100,1K1000000,2Pi100000

对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 1000 , 1 ≤ K ≤ 1000000000 , 2 ≤ P i ≤ 1000000000 1 ≤ N ≤ 1000, 1 ≤ K ≤ 1000000000, 2 ≤ P_i ≤ 1000000000 1N1000,1K1000000000,2Pi1000000000

Output

输出一个分数表示答案

Sample Input

3 4
2
3
5

Sample Output

1/2

题解

因为给出的 p i p_i pi 是质数,所以每一个分数对应的小数都是独一无二的,就像只能有 1 2 \frac{1}{2} 21,而不会有 2 4 \frac{2}{4} 42 一样。

而且当分母一定时,分子的大小顺序就是对应的分数的大小顺序,就像 1 5 < 2 5 < 3 5 < 4 5 \frac{1}{5}<\frac{2}{5}<\frac{3}{5}<\frac{4}{5} 51<52<53<54

那么如果我们可以知道小于小数 m i d mid mid ,且分母为 P P P 的分数的个数 c n t cnt cnt 的话,我们就可以枚举 n n n 个分母求得所有小于 m i d mid mid 的分数的个数 c n t cnt cnt ,通过比较这个 c n t cnt cnt k k k 的大小就可以进行二分了,直到最后 c n t = k cnt = k cnt=k

而每一次求 c n t cnt cnt 时我们都保存最接近 m i d mid mid 的分数的分子和分母,那么二分结束时的分子和分母就是要输出的答案了。

那么怎么获取这个 c n t cnt cnt 呢?我们知道当分母为 5 5 5 时,构成的分数是: 1 5 、 2 5 、 3 5 \frac{1}{5}、\frac{2}{5}、\frac{3}{5} 515253 4 5 \frac{4}{5} 54 ,假设 m i d mid mid 此时为 0.5 0.5 0.5 ,那么把 0.5 0.5 0.5 转化为一个分数且分母为 5 5 5 的最简单的方式就是分子分母同时乘以 5 5 5 0.5 = 5   ⋅   0.5 5 0.5=\frac{5\ ·\ 0.5}{5} 0.5=55  0.5。所以得到的分数就是 2.5 5 \frac{2.5}{5} 52.5,显然,分子小于 2.5 2.5 2.5 的有 2 2 2 个,即 2.5 2.5 2.5 向下取整;同理当分母为 P P P 时,小于 m i d mid mid 的分数的个数就是 ⌊ P   ⋅   m i d ⌋ \lfloor P\ ·\ mid \rfloor P  mid,(符号意为向下取整)。

代码

#include <iostream>
#include <algorithm>
#define maxn 1005
#define _for(i, a) for(LL i = 0; i < (a); ++i)
using namespace std;
typedef long long LL;

LL n, k;
LL P[maxn];
LL Numerator, Denominator;	//最接近mid的分子和分母

LL find(double mid) {
	LL cnt = 0;
	_for(i, n) {
		LL num = mid * P[i];	//向下取整
		cnt += num;
		if (Numerator == -1 && Denominator == -1 || Numerator * P[i] < num * Denominator) {	//保存分子和分母
			Numerator = num;
			Denominator = P[i];
		}
	}
	return cnt;
}

LL gcd(LL a, LL b) {
	if (a > b) swap(a, b);
	return a ? gcd(b % a, a) : b;
}

void sol() {
	cin >> n >> k;
	_for(i, n) cin >> P[i];
	double l = 0, r = 1;
	while (1) {
		Numerator = -1, Denominator = -1;
		double mid = (l + r) / 2;
		LL cnt = find(mid);
		if (cnt == k) break;
		if (cnt > k) r = mid;
		else l = mid;
	}
	LL _gcd = gcd(Numerator, Denominator);
	cout << Numerator / _gcd << "/" << Denominator / _gcd << "\n";
}

int main() {
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	//freopen("in.txt", "r", stdin);

	sol();
	return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值