CF18D 高精度+贪心

http://codeforces.com/problemset/problem/18/D

Last year Bob earned by selling memory sticks. During each of n days of his work one of the two following events took place:

  • A customer came to Bob and asked to sell him a 2x MB
    memory stick. If Bob had such a stick, he sold it and got 2x berllars.
  • Bob won some programming competition and got a 2x MB
    memory stick as a prize. Bob could choose whether to present this memory stick to one of his friends, or keep it.

Bob never kept more than one memory stick, as he feared to mix up their capacities, and deceive a customer unintentionally. It is also known that for each memory stick capacity there was at most one customer, who wanted to buy that memory stick. Now, knowing
all the customers‘ demands and all the prizes won at programming competitions during the last n days, Bob wants to know, how much money he could have earned,
if he had acted optimally.

Input

The first input line contains number n (1?≤?n?≤?5000)
— amount of Bob‘s working days. The following n lines contain the description of the days. Line sell
x stands for a day when a customer came to Bob to buy a 2x MB
memory stick (0?≤?x?≤?2000). It‘s guaranteed that for each x there
is not more than one line sell x. Line win x stands for a
day when Bob won a 2x MB
memory stick (0?≤?x?≤?2000).

Output

Output the maximum possible earnings for Bob in berllars, that he would have had if he had known all the events beforehand. Don‘t forget, please, that Bob can‘t keep more than one memory stick at a time.

Sample test(s)

input

7
win 10
win 5
win 3
sell 5
sell 3
win 10
sell 10

output

1056

input

3
win 5
sell 6
sell 4

output

0
/**
CF 18D 高精度+贪心
题目大意:一个人可以得到2^x的内存,可以卖出2^x的内存换取,2^x的钱,win代表得到,sell代表卖出。但是这个人手中任意时刻只能有一块内存,
          问怎么安排能使获得的钱最多。
解题思路:因为题目中有明确的说明,每种内存最多只能卖一次,所以所有小于x的2的幂加起来也没有2^x大,可以采用贪心,sell从大到小排序,优先处理
          数字略大,要用到高精度
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=5005;

int f[maxn][maxn],ans[maxn],a[maxn];
char s[15];
int n;

int main()
{
    ///预处理出2的0~2000次方
    memset(f,0,sizeof(f));
    f[0][0]=1;
    f[0][1]=1;
    for(int i=1; i<2003; i++)
    {
        int tt=0;
        for(int j=1; j<=f[i-1][0]; j++)
        {
            f[i][j]=f[i-1][j]+f[i-1][j]+tt;
            tt=f[i][j]/10;
            f[i][j]%=10;
            ++f[i][0];
        }
        if(tt)
            f[i][++f[i][0]]=tt;
        /*printf("%d ",i);
        for(int k=f[i][0];k>=1;k--)
             printf("%d",f[i][k]);
         printf("\n");
         getchar();*/
    }
    while(~scanf("%d",&n))
    {
        vector <pair<int,int> >b;
        for(int i=0; i<n; i++)
        {
            scanf("%s%d",s,&a[i]);
            if(s[0]=='s')
                b.push_back(make_pair(a[i],i)),a[i]=-1;
        }
        sort(b.rbegin(),b.rend());
        memset(ans,0,sizeof(ans));
        ans[0]=1;
        for(int i=0; i<b.size(); i++)
        {
            int x=b[i].first;
            int y=b[i].second;
            for(int j=y-1; j>=0&&a[j]!=-2; j--)
            {
                if(a[j]==x)
                {
                    int tt=0;
                   // printf("(%d)\n",a[j]);
                    int bit=max(ans[0],f[x][0]);
                    for(int k=1; k<=bit; k++)
                    {
                        ans[k]+=f[x][k]+tt;
                        tt=ans[k]/10;
                        ans[k]%=10;
                    }
                    if(tt)ans[++bit]+=tt;
                    ans[0]=bit;
                    for(int k=j; k<=y; k++)
                        a[k]=-2;
                    break;
                }
            }
        }
        for(int i=ans[0]; i>=1; i--)
        {
            printf("%d",ans[i]);
        }
        printf("\n");
    }
    return 0;
}
时间: 2024-08-03 01:00:43

CF18D 高精度+贪心的相关文章

洛谷P1080 国王游戏 高精度 贪心 数学推公式

洛谷P1080 国王游戏        数学推公式      高精度    贪心 然而这并不是我打出来的,抄题解... 将左手与右手的乘积从小到大排序,然后计算求最大值即可.(需要高精度) 证明: 1)知道,如果相邻的两个人交换位置,只会影响到这两个人的值,不会影响他人 2)假设相邻的两个人i, i + 1.设A[i] B[i] <= A[i + 1] B[i + 1],i之前所有人的左手乘积为S. 则,ans1 = max{S / B[i], S * A[i] / B[i + 1]} 若交换

CF - 高精度 + 贪心

Last year Bob earned by selling memory sticks. During each of n days of his work one of the two following events took place: A customer came to Bob and asked to sell him a 2x MB memory stick. If Bob had such a stick, he sold it and got 2x berllars. B

【NOIP2012提高组】国王游戏 贪心 + 高精度

题目分析 题目答案不具有单调性,所以不可以二分,转而思考贪心.因为无法确定位置,所以考虑如何才能让对于每一个$1 ~ i$使得$i$的答案最大,即$1 ~ i$最后一个最优.若设对于位置$i$,$a[i]$表示左手,$b[i]$表示右手,$S$为其前面所有人的左手之积,那么他的答案就是$\frac{S}{b[i]}$,如果存在在$i$后边的$j$的答案更优, 即$\frac{S * a[i]}{b[j]} > \frac{S * a[j]}{b[i]} => a[i] * b[i] >

POJ 2325 Persistent Numbers#贪心+高精度除法

(- ̄▽ ̄)-* 这道题涉及高精度除法,模板如下: char s[1005]; char division[1005];//存储进行高精度除法的数据 bool bignum_div(int x) { int tot=0,num=0; for(int i=0;s[i];i++) { num=num*10+s[i]-'0'; division[tot++]=num/x+'0'; num%=x; } division[tot]='\0';//利于进行strcpy() if(num==0) //有适合的

[贪心][高精度][NOIP]国王游戏

题目梗概 有n个大臣,他们可以拿到他们之前所有人左手数的乘积除以他的右手,问是否能通过调换位置来使拿钱最多的大臣拿的钱最少. 思考 贪心证明: 设相邻的两个人$i, i + 1$.设$A[i] \times B[i] \leqslant  A[i + 1] B[i + 1]$,i之前所有人的左手乘积为S. 则,$ans1 = max \left (\frac{S}{B[i]} , \frac{S}{A[i] \times B[i+1]}  \right )$ 若交换 $ans2 = max \l

【POJ2325】Persistent Numbers 贪心+高精度/低精度

题意:我们可以把一个数A变成B=A的各位乘积,现在给出B,求是否可以有某个A通过计算得到B,有的话,是多少. 题解:贪心. 我们先分解B,若质因数有大于等于10的显然就不行了. 否则则一定可以把他的各因数排在一起成为A,使A的各位乘积=B. 贪心策略:把小数放前面. 注意: 一.不一定要质因数,10以内即可. 二.需要高精度. 三.A!=B 代码: #include <cstdio> #include <cstring> #include <algorithm> #de

【NOIP 2012 国王游戏】 贪心+高精度

题目描述 恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右 手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n 位大臣排 成一排,国王站在队伍的最前面.排好队后,所有的大臣都会获得国王奖赏的若干金币,每 位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右 手上的数,然后向下取整得到的结果. 国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序, 使得获得奖赏最多的大臣,所获奖赏尽可能的少

【贪心】【高精度】zoj3987 Numbers

题意:给你一个数n,让你找m个非负整数,使得它们的和为n,并且按位或起来以后的值最小化.输出这个值. 从高位到低位枚举最终结果,假设当前是第i位,如果m*(2^i-1)<n的话,那么说明这一位如果填零,剩下的位不论怎么填,都绝对凑不出n来,所以这一位必须填1.如果m*(2^i-1)>=n,这一位就填1,然后把n变为max(n mod 2^i , n-m*2^i),重复这个过程即可. 要用高精度. import java.util.*; import java.io.*; import java

洛谷P1080(NOIP2012)国王游戏——贪心排序与高精度

题目:https://www.luogu.org/problemnew/show/P1080 排序方法的确定,只需任取两个人,通过比较与推导,可以得出ai*bi小的人排在前面: 高精度写的时候犯了些细节错误,详见注释. 代码如下: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define MAXN 200005 using namespace std;