Epic Fail of a Genie


题目描述:

E. Epic Fail of a Genie

Time Limit: Unknown ms

Memory Limit: 65536KB
64-bit integer IO format: %I64d Java class name: (Any)

Submit Status PID: 49355

Input/Output: standard input/output

Aladdin had found a new shiny lamp and has started polishing it with his hands. Suddenly a mysterious genie appeared from within and offered Aladdin to fulfill any of his three wishes. Genie had a very subtle humor that made Aladdin very sceptical about him. Aladdin didn’t believe that genie was so powerful that could do anything he had wished and asked him to become a mouse. The genie did that without hesitation. Then Aladdin asked genie to become a mouse pad. Genie didn’t like this kind of wish but had to submit. Finally Aladdin tested genie’s abilities in math: he had to choose a nonempty subset giving the maximum product from the given set of numbers. Genie was shocked. Math was his Achilles’ heel, however he was able to contact anyone on earth to help him. You are a secret weapon of the genie — help him solve the test and avoid this epic fail. This is the last chance for the genie: he’ll be forever jailed in the lamp if his new master doesn’t trust him.

Input

The first line of input contains an integer N (2 ≤ N ≤ 104) — the cardinality of a set of numbers.

The second line of input contains N floating-point numbers with absolute value not more than 106. The fractional part of each number does not contain more than two digits.

Output

The first line of the output should contain a single integer M — the total number of numbers that genie should choose from the set.

The second line of output should contain 1-based indexes of these numbers. Indexes must be sorted in ascending order. If multiple solutions exist please output the one with the minimal subset cardinality. If there are still several suitable solutions output any of them.

Sample Input

Input
7
1 3 0 -1 -2 0.5 3

Output
4
2 4 5 7

题解:

第一反应当然是dp,维护前面的一个正数的最大值,和一个负数的绝对值的最大值.但是乘起来的数太大了.最后看昂神的代码,可以取log,因为取log的缘故,那么我们只进行绝对值的运算,用一个tag来记录这个数的符号.注意,在昂神队的代码中有一个*100000-1的过程,因为log之后的数有点小,不如全部放大一点.而且,初始化的0初始化为-INF,他们选择的是-1e60.
解法二(2):其实是有贪心性质的,当时能搞出这个思路队友还是挺牛的:) 就是取大于1的然后分类讨论balabala..

重点:

dp的方法:取log 同时乘一个数 tag打正负 初始化0的-INF
贪心的思想

代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <ctype.h>
#include <limits.h>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
#define CLR(a) memset(a, 0, sizeof(a))
#define REP(i, a, b) for(int i = a;i < b;i++)
#define REP_D(i, a, b) for(int i = a;i <= b;i++)

typedef long long ll;

using namespace std;

const double eps = 1e-7;

struct info
{
    int num, id;
    info(int _num = 0, int _id = 0)
    {
        num = _num;
        id = _id;
    }
    bool operator < (const info b) const
    {
        return num < b.num;
    }
};
vector<info> bigPos, bigNa, smallPos, smallNa, zero;
vector<int> ans;
int n;
void outPut()
{
    sort(ans.begin(), ans.end());
    printf("%d\n", ans.size());
    for(int i = 0;i<ans.size();i++)
        printf("%d%c", ans[i], (i==ans.size()-1?'\n':' '));
}

void solve()
{
    bigPos.clear();
    bigNa.clear();
    smallPos.clear();
    smallNa.clear();
    zero.clear();
    ///
    for(int i = 1;i<=n;i++)
    {
        double x;
        int t;
        scanf("%lf", &x);
        if(x>eps)
            t = ((x*100)+eps);
        else if(x < -eps)
            t = ((x*100)-eps);
        else
            t = 0;
        if(t > 100)
            bigPos.push_back(info(t, i));
        else if(t < -100)
            bigNa.push_back(info(t, i));
        else if(t > 0)
            smallPos.push_back(info(t, i));
        else if(t < 0)
            smallNa.push_back(info(t, i));
        else
            zero.push_back(info(t, i));
    }
    
    sort(bigPos.begin(), bigPos.end());
    sort(smallPos.begin(), smallPos.end());
    sort(bigNa.begin(), bigNa.end());
    sort(smallNa.begin(), smallNa.end());
    sort(zero.begin(), zero.end());
    ans.clear();
    if(bigNa.size()%2==0)
    {
        for(int i = 0;i<bigNa.size();i++)
            ans.push_back(bigNa[i].id);
        for(int i = 0;i<bigPos.size();i++)
            ans.push_back(bigPos[i].id);
        if(ans.size()!=0)
        {
            outPut();
            return;
        }
        if(smallNa.size() >= 2 || smallPos.size() >= 1)
        {
            ll pos = -1;
            ll na = -1;
            if(smallPos.size() >= 1)
                pos = (ll)smallPos[smallPos.size()-1].num*(ll)100;
            if(smallNa.size() >= 2)
                na = (ll)smallNa[0].num*(ll)smallNa[1].num;
            if(na > pos)
            {
                ans.push_back(smallNa[0].id);
                ans.push_back(smallNa[1].id);
                outPut();
                return;
            }
            else
            {
                ans.push_back(smallPos[smallPos.size()-1].id);
                outPut();
                return;
            }
        }
        else
        {
            if(zero.size() >= 1)
            {
                ans.push_back(zero[0].id);
                outPut();
                return;
            }
            else
            {
                ///
                ans.push_back(smallNa[smallNa.size()-1].id);
                outPut();
                return;
            }
        }
    }
    else
    {
        for(int i = 0;i<bigNa.size() - 1;i++)
            ans.push_back(bigNa[i].id);
        for(int i = 0;i<bigPos.size();i++)
            ans.push_back(bigPos[i].id);
        if(ans.size()!=0)
        {
            if(smallNa.size() >= 1)
            {
                ll tmp = (ll)smallNa[0].num*(ll)bigNa[bigNa.size()-1].num;
                if(tmp > 10000)
                {
                    ans.push_back(bigNa[bigNa.size()-1].id);
                    ans.push_back(smallNa[0].id);
                }
            }
            outPut();
            return;
        }
        else
        {
            if(smallNa.size()>=1 || smallPos.size() >= 1)
            {
                //printf("%d %d---\n", smallNa[0].num, bigNa[bigNa.size()-1].num);
                ll pos = -1, na = -1;
                if(smallNa.size() >= 1)
                    na = (ll)smallNa[0].num*(ll)bigNa[bigNa.size()-1].num;
                if(smallPos.size() >= 1)
                    pos = (ll)smallPos[smallPos.size()-1].num*(ll)100;
                if(na > pos)
                {
                    ans.push_back(bigNa[bigNa.size()-1].id);
                    ans.push_back(smallNa[0].id);
                    outPut();
                    return;
                }
                else
                {
                    ans.push_back(smallPos[smallPos.size()-1].id);
                    outPut();
                    return;
                }
            }
            else
            {
                if(zero.size()>=1)
                {
                    ans.push_back(zero[0].id);
                    outPut();
                    return;
                }
                else
                {
                    ans.push_back(bigNa[bigNa.size()-1].id);
                    outPut();
                    return;
                }
            }
        }
    }
}

int main()
{
   // freopen("13Min.txt", "r", stdin);
    //freopen("1out.txt", "w", stdout);
    while(scanf("%d", &n) != EOF)
        solve();
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值