NOIP2012 国王游戏
贪心还是很舒服的,不过加上高精度就很难受……
我们要求的是得到金钱最多的大臣得到的钱数尽可能少。看到这个问题可能会想起二分答案之类的……不过看看这数据范围就知道不可能。想起之前做过一道类似的题,考虑一下贪心。
直接贪心肯定是看不出来啥,那我们还是老套路,交换一下两个大臣。假设前面所有人乘积为w,第一个大臣左右手上的数为l1,r1,第二个为l2,r2.那么第一个大臣得到的钱就是w / r1,第二个是w * l1 / r2.交换之后,第一个大臣得到的是w / r2,第二个大臣得到的是w * l2 / r1,很显然我们只要比较w * l1 / r2和w * l2 / r1的大小即可。进行移项之后,发现w * l1 / r2 > w * l2 / r1的条件是l1 * r1 > l2 * r2.不过我们为了尽量让多的更少,所以我们肯定要逆着它来,把l,r乘积较大的大臣放在后面即可。
之后就要上高精度了……好久没写高精度,这次补上了一发自己的高精度模板吧……只需要高精乘和高精除低精还是可以的。用重载运算符写题真爽
看一下代码。
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<queue> #include<cstring> #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define enter putchar('\n') #define pr pair<int,int> #define mp make_pair #define fi first #define sc second using namespace std; typedef long long ll; const int M = 5005; const int N = 10000005; ll read() { ll ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >='0' && ch <= '9') { ans *= 10; ans += ch - '0'; ch = getchar(); } return ans * op; } struct dc { ll l,r; bool operator < (const dc &g) const { return l * r < g.l * g.r; } }c[M]; struct big { int f[M],len; big() { memset(f,0,sizeof(f)),len = 0; } big change(int k) { big a; while(k) a.f[a.len++] = k % 10,k /= 10; while(!a.f[a.len] && a.len > 0) a.len--; return a; } void modi(int k) { while(k) f[len++] = k % 10,k /= 10; while(!f[len] && len > 0) len--; } big operator * (const big &g) const { big c; c.len = len + g.len + 1; //printf("!%d %d %d\n",len,g.len,c.len); rep(i,0,len) rep(j,0,g.len) c.f[i+j] += f[i] * g.f[j]; rep(i,0,c.len-1) c.f[i+1] += c.f[i] / 10,c.f[i] %= 10; while(!c.f[c.len] && c.len > 0) c.len--; return c; } big operator / (const int &g) { big c; int cur = 0; per(i,len,0) cur *= 10,cur += f[i],c.f[c.len++] = cur / g,cur %= g; reverse(c.f,c.f + c.len); while(!c.f[c.len] && c.len > 0) c.len--; return c; } void print() { per(i,len,0) printf("%d",f[i]);enter; } }kl,kr,ans; ll ka,kb,n; big bmax(const big &a,const big &b) { if(a.len != b.len) return a.len > b.len ? a : b; per(i,a.len,0) { if(a.f[i] == b.f[i]) continue; else return a.f[i] > b.f[i] ? a : b; } return a; } int main() { n = read(); ka = read(),kb = read(); kl.modi(ka),kr.modi(kb); //kl.print(),kr.print(); rep(i,1,n) c[i].l = read(),c[i].r = read(); sort(c+1,c+1+n); rep(i,1,n) { big L,R; L.modi(c[i].l); //L.print();putchar('#'); big cur = kl / c[i].r; ans = bmax(ans,cur); kl = kl * L; //kl.print(); } ans.print(); return 0; }
当你意识到,每个上一秒都成为永恒。