您的位置:首页 > 其它

NOIP 2012 国王游戏 贪心 高精度 (COGS 1263)

2015-09-17 19:32 393 查看
T^T,太桑心了,自己搞了好长时间的高精度,当最终搞出来没问题的高精度之后,就来写这道题了。却不曾想到自己倍增式的低级高精除T掉了。T^T……

还是再好好搞搞高精除吧。。。

来说这道题的贪心思路,又是一个与顺序相关的,不过与上一次写的那个矩形分割不同,这个并不是很容易能看出来或想出来,需要写一写。

假设一个最佳序列a1,a2,a3,a4……i,j……an。

设k = l[a1]*l[a2]*l[a3]*……*l[i-1];

考虑对于任意1 <= i < n (j == i+1),交换i和j的位置,因为之前是最优的,那么交换i,j后一定不如之前的优,即有:k*l[i]/r[i] <= k*l[j]/r[i],稍微变形即有l[i]*r[i] <= l[j]*r[j],即l[i]*r[i] <= l[i+1]*r[i+1]。

那么就有了贪心的依据:l[i]*r[i]的升序排列是“最优”的排列。为什么加引号呢?因为这个最优是一个特殊的概念,因为我们保持的是每组i,i+1都满足这个条件,而改变其中一些可能不会影响最大值,就像样例中有好多种排序方式都得到2的结果一样。

不过我们只需要最后结果正确就好了,不要太在意这个。

然而自己并没有AC,因为渣渣一样的高精度。。。暂时没有代码。T^T.

过了10min后AC啦,自己写的高精除高精太慢。。于是改成了高精除单精,模拟竖式还是很快的。

不过注意这道题最多大概会出现5000位数,高精度的数组不要开小了。

#include <cstdio>
#include <algorithm>
#include <cstring>
#define M 1005
#define P 10000
using namespace std;

int n;
char s[M];

struct BigInt{
int a[M], h;
bool neg;

BigInt(){
h = neg = 0;
memset(a, 0, sizeof a);
}

void read(){
memset(s, 0, sizeof s);
scanf("%s", s+1);
int len = strlen(s+1);
h = 1;
for(int i = len, j = 1; i; i--, j *= 10){
if(j == P){
j = 1;
h++;
}
a[h] += (s[i]-'0')*j;
}
}

void read(char *s){
int len = strlen(s);
h = 1;
for(int i = len-1, j = 1; i >= 0; i--, j *= 10){
if(j == P){
j = 1;
h++;
}
a[h] += (s[i]-'0')*j;
}
}

bool operator < (BigInt k) const {
if(h > k.h) return 0;
if(h < k.h) return 1;
for(int i = h; i; i--){
if(a[i] > k.a[i]){
return 0;
}
if(a[i] < k.a[i]){
return 1;
}
}
return 0;
}

bool operator > (BigInt k) const {
if(h > k.h) return 1;
if(h < k.h) return 0;
for(int i = h; i; i--){
if(a[i] > k.a[i]){
return 1;
}
if(a[i] < k.a[i]){
return 0;
}
}
return 0;
}

bool operator == (BigInt k) const {
if(h != k.h) return 0;
for(int i = h; i; i--){
if(a[i] != k.a[i]) return 0;
}
return 1;
}

BigInt operator + (BigInt k) const {
BigInt res = *this;
res.h = max(res.h, k.h);
for(int i = 1; i <= res.h; i++){
res.a[i] += k.a[i];
res.a[i+1] += res.a[i] / P;
res.a[i] %= P;
}
while(res.a[res.h+1]) res.h++;
return res;
}

BigInt operator - (BigInt k) const {
BigInt res = *this;
for(int i = 1; i <= k.h; i++){
res.a[i] -= k.a[i];
if(res.a[i] < 0){
res.a[i] += P;
res.a[i-1]--;
}
}
return res;
}

BigInt operator * (BigInt k) const {
BigInt res;
if(!h || !k.h) return res;
for(int i = 1; i <= h; i++)
for(int j = 1; j <= k.h; j++){
res.a[i+j-1] += a[i] * k.a[j];
res.a[i+j] += res.a[i+j-1] / P;
res.a[i+j-1] %= P;
}
res.h = h + k.h + 2;
while(!res.a[res.h] && res.h) res.h--;
return res;
}

BigInt operator * (int k) const {
BigInt res;
if(!h || !k) return res;
for(int i = 1; i <= h; i++){
res.a[i] += a[i] * k;
res.a[i+1] += res.a[i] / P;
res.a[i] %= P;
}
res.h = h + 2;
while(!res.a[res.h] && res.h) res.h--;
return res;
}

BigInt operator / (BigInt k) const {
BigInt res, two;
int cha = h - k.h;
if(cha > 1){
cha--;
res.h = 1;
res.a[2] = cha;
res.a[1] = cha * P % P;
while(res.a[res.h+1]){
res.h++;
res.a[res.h+1] += res.a[h] / P;
res.a[h] %= P;
}
}
two.h = 1;
two.a[1] = 2;
#define RES k*res+k
while(RES < *this || RES == *this){
BigInt t;
t.h = t.a[1] = 1;
while(k*(t+res)*two < *this || k*(t+res)*two == *this){
t = t * two;
}
res = res + t;
}
return res;
}

BigInt operator / (int k) const {
BigInt res;
int x = 0;
for(int i = h; i; i--){
res.a[i] = (x*P + a[i]) / k;
x = (x*P + a[i]) % k;
}
res.h = h;
while(!res.a[res.h] && res.h) res.h--;
return res;
}

void print(){
if(!h) {
printf("0");
return;
}
if(neg) printf("-");
printf("%d", a[h]);
for(int i = h-1; i; i--){
int k = a[i], len = 1;
while(k){
len *= 10;
k /= 10;
}
if(len==1) len *= 10;
while(len < P){
printf("0");
len *= 10;
}
printf("%d", a[i]);
}
}
}l, r, k, ans;

struct peo{
BigInt l, w;
int r;
bool operator < (peo k) const {
return w < k.w;
}
}p[1005];

int main()
{
scanf("%d", &n);
l.read();
r.read();
for(int i = 1; i <= n; i++){
p[i].l.read();
scanf("%d", &p[i].r);
p[i].w = p[i].l * p[i].r;
}
sort(p+1, p+n+1);

k = l;
for(int i = 1; i <= n; i++){
ans = max(ans, k/p[i].r);
k = k * p[i].l;
}
ans.print();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: