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位数,高精度的数组不要开小了。
还是再好好搞搞高精除吧。。。
来说这道题的贪心思路,又是一个与顺序相关的,不过与上一次写的那个矩形分割不同,这个并不是很容易能看出来或想出来,需要写一写。
假设一个最佳序列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; }
相关文章推荐
- ubuntu截图方法
- Hadoop笔记之自定义分组实现
- crontab命令 :Linux下定时执行脚本
- 测试
- struts2 开发流程以及配置文件
- SQL 语句
- iOS中NSThread(主线程,子线程)
- ipad开发中UIPopoverController中自定义view在Xcode6中尺寸匹配问题
- Activity显示关闭动画
- java分页工具类
- c++ primer 学习笔记-第十五章
- flv视频播放demo
- 数据结构学习小结(1)-----线性结构-----线性表
- Java泛型学习笔记
- Objective-C中为何用copy修饰block
- Search for a range寻找上下界-Leetcode
- DIDAO.Common --- 项目中的常用类及其中函数
- sevlet1
- UVa 1626:Brackets Sequence(DP)
- VS各版本解决方案转换工具 SolutionConverter2015