CodeForces Gym 100685E Epic Fail of a Genie (贪心,控制精度)

题意:给定 n 个数,然后让从中选取一些数使得它们的总乘积最大。如果有多个,要求这些数尽量少,如果还有多个,随便输出一组即可。

析:一个贪心题,根据乘法的性质,很容易知道,如果一个数大于1,那么肯定要选的,然后如果有两个负数乘积大于1,也要选上,其他的尽量不要选。

最后如果没有这样数,那么就只要计算最小的两个数乘积与最大的比较即可,主要是因为是最小的两个可能是负数,如果不是也不影响结果。

这个题在比赛时,竟然没有AC,。。。主要原因是我没有控制精度,卡了好久,如果控制一下精度就AC了,可以把所有的实数都乘以100,然后再计算。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std;

typedef long long LL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 1e4 + 5;
const int mod = 1e9 + 7;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline int Min(int a, int b){ return a < b ? a : b; }
inline int Max(int a, int b){ return a > b ? a : b; }
inline LL Min(LL a, LL b){ return a < b ? a : b; }
inline LL Max(LL a, LL b){ return a > b ? a : b; }
inline bool is_in(int r, int c){
    return r >= 0 && r < n && c >= 0 && c < m;
}
struct node{
    int id;
    LL val;
    bool operator < (const node &p) const{
        return val < p.val;
    }
};
node a[maxn];
vector<int> ans;

int main(){
    while(scanf("%d", &n) == 1){
        double x;
        for(int i = 0; i < n; ++i){
            scanf("%lf", &x);
            a[i].val = x * 100.0;
            a[i].id = i+1;
        }
        sort(a, a+n);
        ans.clear();
        int cnt = 0;
        for(int i = 0; i < n; ++i){
            if(a[i].val < -100LL){
                if(i+1 < n && a[i].val * a[i+1].val > 10000LL){
                        ans.push_back(a[i].id), ans.push_back(a[i+1].id), ++i;
                }
            }
            else if(a[i].val > 100LL)  ans.push_back(a[i].id);
        }

        if(ans.empty()){
            LL s = a[0].val * a[1].val;
            if(s > a[n-1].val * 100LL)  ans.push_back(a[0].id), ans.push_back(a[1].id);
            else  ans.push_back(a[n-1].id);
        }
        printf("%d\n", ans.size());
        sort(ans.begin(), ans.end());
        for(int i = 0; i < ans.size(); ++i){
            if(i)  putchar(‘ ‘);
            printf("%d", ans[i]);
        }
        printf("\n");
    }
    return 0;
}
时间: 2024-08-01 17:34:44

CodeForces Gym 100685E Epic Fail of a Genie (贪心,控制精度)的相关文章

codeforce Gym 100685E Epic Fail of a Genie(贪心)

题意:给出一堆元素,求一个子集,使子集的乘积最大,如有多个,应该使子集元素个数尽量小. 题解:贪心,如果有乘积大于1的正数,那么是一定要选的,注意负数也可能凑出大于1的正数,那么将绝对值大于1的负数两两配对,如果还剩下一个,那么在判断一下,那个负数和比它小的最小负数的乘积是否大于1,如果是那么就选这两个.把所有可能凑成大于1的数选完以后,剩下的数一定比1小,那么就不选. 如果无法凑出大于1的数,那么再分类讨论一下. 挺容易写错... #include<bits/stdc++.h> using

Codeforces gym 100685 E. Epic Fail of a Genie 贪心

E. Epic Fail of a GenieTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100685/problem/E Description Aladdin had found a new shiny lamp and has started polishing it with his hands. Suddenly a mysterious genie appeared from withi

Codeforces Gym 101174 A Within Arm&#39;s Reach 贪心 手臂

#include<iostream> #include<stdio.h> #include <string.h> #include <algorithm> #include <vector> #include <math.h> using namespace std; #define LL long long const int maxn=25; double a[maxn],l[maxn],r[maxn]; double ex,ey

Codeforces gym Hello 2015 Div1 B and Div2 D

Codeforces gym 100571 problem D Problem 给一个有向图G<V,E>和源点S,边的属性有长度L和颜色C,即E=<L,C>.进行Q次询问,每次给定一个点X,输出S到X的最短路的长度(不存在则输出 -1).但要求S到X的路径中相邻两条边颜色不一样. Limits Time Limit(ms): 1000 Memory Limit(MB): 256 |V|, |E|: [1, 10^5] X, S: [1, |V| ] L: [1, 10^9] |C|

Codeforces gym Hello 2015 Div1 E

Codeforces gym 100570 problem E (一种处理动态最长回文子串问题的方法) Problem 给一个长度为N的字符串S,字符集是'a'-'z'.进行Q次操作,操作分三种.一,修改位置X的字符为C:二,查询以P位置为中心的最长回文子串的长度,并输出:三,查询以P与P+1的中间位置为中心的最长回文子串的长度,并输出. More 第二种操作子串长度为奇数,一定存在:第三种操作子串长度为偶数,若不存在,输出 -1. Limits Time Limit(ms): 4000(1s足

Codeforces gym Hello 2015 Div1 C and Div2 E

Codeforces gym 100570 problem C Codeforces gym 100571 problem E Problem 给一个N行M列的矩阵Ma,进行Q次(Q<=10)查询,每次给定一个K,问有多少子矩阵,满足最大值max - 最小值min <=K. Limits Time Limit(ms): 8000 Memory Limit(MB): 512 N, M: [1, 400] Q: [1, 10] Ma(i, j), K: [1, 10^9] Solution (Th

程序员的Epic Fail [0]

作为程序员,我们经常会被客户问的一个问题一定是不是说很容易么,为什么花了这么长时间.不得不说,程序员可能是最糟糕的计划者,按时按点按计划完成的软件项目永远是下一个项目.一个项目的延期,有很多这样那样的原因,其中不得不说的一个原因就是很多代码想起来很容易,但是真的写起来,细节里全是魔鬼.在这个Epic Fail的系列中,我会记录一些在我平常写代码的过程中遇到的那些本来很简单却花了很长时间的有趣问题.这个系列会不定时更新,不断记录我写代码中的糗事,希望我永远不用更新:). 作为开篇,记录一个花了我1

【模拟】ECNA 2015 I What&#39;s on the Grille? (Codeforces GYM 100825)

题目链接: http://codeforces.com/gym/100825 题目大意: 栅栏密码.给定N(N<=10),密钥为一个N*N的矩阵,'.'代表空格可以看到,'X'代表被遮挡,还有密文字符串S,长度为N*N 每次将这个矩阵顺时针旋转90°,把矩阵中空格对应的位置按照从上到下从左到右的顺序依次填充上密文字符,求最终这个密文字符能否填满N*N的矩阵,能按顺序输出得到的答案,不能输出"invalid grille" 题目思路: [模拟] 直接模拟即可.旋转的坐标公式很好推.

Codeforces gym Hello 2015 Div2 B

Codeforces gym 100571 problem B Problem 设函数F(x),F(1)与F(2)已知,且当 i>=3,F(i)=a*F(i-2)+b*F(i-1).再给一个长度为N的数列A,进行Q次如下操作:每次给一个区间[L, R],对于每个k(L=<k<=R),将A[k]=A[k]+F[k-L+1].最后输出数列A(mod 10^9+7). Limits Time Limit(ms): 1000 Memory Limit(MB): 256 N, Q: [1, 10^