hdu5073 简单枚举+精度处理

其实这题还是挺简单的,因为移动k个星球后,这k个星球的权值就可以变为0,所以只有剩下的本来就是连着的才是最优解,也就是说要动也是动两端的,那么就O(N)枚举一遍动哪些就好了。

我是在杭电oj题目重现的比赛上做这题,因为之前听人说现场赛时有人用n^2的算法蹭过了,所以我不断蹭,蹭了一个小时都没蹭过。。。~!@#¥%……

先贴一份乱七八糟想蹭过的代码

/*
 * Author    : ben
 */
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <stack>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <functional>
#include <numeric>
#include <cctype>
using namespace std;
typedef long long LL;
const double eps = 1e-9;
int get_int() {
    int res = 0, ch;
    while (!((ch = getchar()) >= ‘0‘ && ch <= ‘9‘)) {
        if (ch == EOF)
            return 1 << 30;
    }
    res = ch - ‘0‘;
    while ((ch = getchar()) >= ‘0‘ && ch <= ‘9‘)
        res = res * 10 + (ch - ‘0‘);
    return res;
}
//输入整数(包括负整数),用法int a = get_int2();
int get_int2() {
    int res = 0, ch, flag = 0;
    while (!((ch = getchar()) >= ‘0‘ && ch <= ‘9‘)) {
        if (ch == ‘-‘)
            flag = 1;
        if (ch == EOF)
            return 1 << 30;
    }
    res = ch - ‘0‘;
    while ((ch = getchar()) >= ‘0‘ && ch <= ‘9‘)
        res = res * 10 + (ch - ‘0‘);
    if (flag == 1)
        res = -res;
    return res;
}
const int MAXN = 50100;
int N, K, data[MAXN];
int ndata[MAXN];
LL sum[MAXN];
double ans;

inline double getCenter(int s, int e) {
    LL su = sum[e];
    if (s > 0) {
        su -= sum[s - 1];
    }
    double ret = su / (e - s + 1.0);
    return ret;
}

void comput(int s, int e, double c) {
    double ret = 0;
    for (int i = s; i <= e; i++) {
        ret += (data[i] - c) * (data[i] - c);
        if (ret > ans) {
            return;
        }
    }
    if (ret < ans) {
        ans = ret;
    }
}

double comput(double c) {
    double ret = 0;
    for (int i = 0; i < N; ) {
        ret += (data[i] - c) * (data[i] - c) * ndata[i];
        i += ndata[i];
    }
    return ret;
}

void work() {
    double cen = getCenter(0, N - 1);
//    printf("cen = %f\n", cen);
    ans = comput(cen);
    for (int a = K; a >= 0; a--) {
        if (ans < eps) {
            break;
        }
        int e = N + a - K - 1;
        double tmpc = getCenter(a, e);
        comput(a, e, tmpc);
    }
}

void treat() {
    for (int i = 0; i < N; i++) {
        int d = data[i];
        int j = i + 1;
        while (j < N && data[j] == d) {
            j++;
        }
        int num = j - i;
        for (j--; j >= i; j--) {
            ndata[j] = num - j + i;
        }
    }
}

int main() {
    int T = get_int();
    while (T--) {
        N = get_int();
        K = get_int();
        for (int i = 0; i < N; i++) {
            data[i] = get_int2();
        }
        sort(data, data + N);
        treat();
        sum[0] = data[0];
        for (int i = 1; i < N; i++) {
            sum[i] = sum[i - 1] + data[i];
        }
        work();
        printf("%.10lf\n", ans);
    }
    return 0;
}

下面是正常做法,其实相对于上面的代码也就只有一处改进,因为上面那份代码求解(xi-x)^2的时候是依次计算累加的,可以通过展开公式,通过预存前n项平方和的方式来计算,把这个计算过程从O(N)变成O(1),就可以过了。

不过我还是wa了几发,原因是一开始忘了对N==K和N-1==K的情况作特殊处理了,因为我后面的代码这个地方没单独考虑。

  1 /*
  2  * Author    : ben
  3  */
  4 #include <cstdio>
  5 #include <cstdlib>
  6 #include <cstring>
  7 #include <cmath>
  8 #include <ctime>
  9 #include <iostream>
 10 #include <algorithm>
 11 #include <queue>
 12 #include <set>
 13 #include <map>
 14 #include <stack>
 15 #include <string>
 16 #include <vector>
 17 #include <deque>
 18 #include <list>
 19 #include <functional>
 20 #include <cctype>
 21 using namespace std;
 22 typedef long long LL;
 23 const double eps = 1e-9;
 24 const int MAXN = 50100;
 25 int N, K;
 26 LL data[MAXN], sum[MAXN], sum2[MAXN];
 27 double ans;
 28 int get_int() {
 29     int res = 0, ch;
 30     while (!((ch = getchar()) >= ‘0‘ && ch <= ‘9‘)) {
 31         if (ch == EOF)
 32             return 1 << 30;
 33     }
 34     res = ch - ‘0‘;
 35     while ((ch = getchar()) >= ‘0‘ && ch <= ‘9‘)
 36         res = res * 10 + (ch - ‘0‘);
 37     return res;
 38 }
 39
 40 //输入整数(包括负整数),用法int a = get_int2();
 41 int get_int2() {
 42     int res = 0, ch, flag = 0;
 43     while (!((ch = getchar()) >= ‘0‘ && ch <= ‘9‘)) {
 44         if (ch == ‘-‘)
 45             flag = 1;
 46         if (ch == EOF)
 47             return 1 << 30;
 48     }
 49     res = ch - ‘0‘;
 50     while ((ch = getchar()) >= ‘0‘ && ch <= ‘9‘)
 51         res = res * 10 + (ch - ‘0‘);
 52     if (flag == 1)
 53         res = -res;
 54     return res;
 55 }
 56 inline LL getSum(int from, int to) {
 57     LL ret = sum[to];
 58     if (from > 0) {
 59         ret -= sum[from - 1];
 60     }
 61     return ret;
 62 }
 63
 64 inline LL getSum2(int from, int to) {
 65     LL ret = sum2[to];
 66     if (from > 0) {
 67         ret -= sum2[from - 1];
 68     }
 69     return ret;
 70 }
 71
 72 inline double getCenter(int s, int e) {
 73     LL su = sum[e];
 74     if (s > 0) {
 75         su -= sum[s - 1];
 76     }
 77     double ret = su / (e - s + 1.0);
 78     return ret;
 79 }
 80
 81 inline double comput(int s, int e, double c) {
 82     LL s1 = getSum(s, e);
 83     LL s2 = getSum2(s, e);
 84     double ret = s2 + (e - s + 1.0) * c * c - 2.0 * c * s1;
 85     return ret;
 86 }
 87
 88 void work() {
 89     double cen = getCenter(0, N - 1);
 90     ans = comput(0, N - 1, cen);
 91     for (int a = 0; a <= K; a++) {
 92         int e = N + a - K - 1;
 93         double tmpc = getCenter(a, e);
 94         double ret = comput(a, e, tmpc);
 95         if (ret < ans) {
 96             ans = ret;
 97         }
 98     }
 99 }
100
101 int main() {
102 #ifndef ONLINE_JUDGE
103     freopen("data.in", "r", stdin);
104 #endif
105     int T= get_int();
106     while (T--) {
107         N = get_int();
108         K = get_int();
109         for (int i = 0; i < N; i++) {
110             data[i] = get_int2();
111         }
112         if (K == N || N - 1 == K) {
113             printf("0\n");
114             continue;
115         }
116         sort(data, data + N);
117         sum[0] = data[0];
118         sum2[0] = data[0] * data[0];
119         for (int i = 1; i < N; i++) {
120             sum[i] = sum[i - 1] + data[i];
121             sum2[i] = sum2[i - 1] + data[i] * data[i];
122         }
123         work();
124         printf("%.10lf\n", ans);
125     }
126     return 0;
127 }
时间: 2024-10-12 04:01:59

hdu5073 简单枚举+精度处理的相关文章

简单除法(简单枚举优化)

#include<iostream> #include<algorithm> using namespace std; void panduan(int s,int k) { int n,m;bool l=1; n=s;m=k; int i,sn=0,a[20],j; for(i=0;n!=0;i++) { a[i]=n%10; n=n/10; } for(;m!=0;i++) { a[i]=m%10; m=m/10; } i--; sort(a,a+i); if(i==8) {a

UVa 725 Division --- 简单枚举

题目链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=666 /* UVa 725 Division --- 简单枚举 */ #include <cstdio> #include <cstring> bool used[10]; /* 判断传进来的两个数是否满足条件 */ bool judge(int a, i

UVA - 10167 - Birthday Cake (简单枚举)

思路:简单枚举 AC代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> using namespace std; int x[105], y[105]; int main() { int A, B, N; while(scanf("%d", &N), N) { for(int

Java练习 SDUT-1959_简单枚举类型——植物与颜色

简单枚举类型--植物与颜色 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 请定义具有red, orange, yellow, green, blue, violet六种颜色的枚举类型color,根据输入的颜色名称,输出以下六种植物花朵的颜色: Rose(red), Poppies(orange), Sunflower(yellow), Grass(green), Bluebells(blue), Violets(v

POJ1449 &amp; ZOJ1036 Enigma(简单枚举)

本文纯属原创,转载请注明出处.谢谢. 题目传送门:http://poj.org/problem?id=1449 Time Limit: 1000MS   Memory Limit: 10000K       Description During the Second World War, the German military forces mainly used one special machine to secure their communication: the Enigma (see

UVA 725 UVA 10976 简单枚举

UVA 725 题意:0~9十个数组成两个5位数(或0开头的四位数),要求两数之商等于输入的数据n.abcde/fghij=n. 思路:暴力枚举,枚举fghij的情况算出abcde判断是否符合题目条件.(注意前导零的判断) 枚举的方法为 for(int i=1234;i<=100000/n;i++){} #include<cstdio> #include<cstring> int num[10]; bool check(int a,int b) { memset(num,0,

简单枚举---从一数组中任取n个元素

这个问题很明显的需要用枚举的思想来一一遍历数组元素并进行无重复组合 给出一个数组a[14]={1,2,3,4,5,6,7,8,9,10,11,12,13,14},求从中任取n个元素的所有组合 如果任取1个元素+取所有元素:15种可能 如果任取2个元素:C^2 14=91  递归组合 1 2    1 3    1 4  1 5   1 6 1 7 1 8 1 9 1 10 1 11 1 12   1 13   1 14   14种 2 3   2 4  2 5  2  6   ... 13种 1

hdu5258简单枚举

百度之星复赛第一题.不明白这么水的题为何一堆人没过...这些人是咋晋级复赛的呢... /* * Author : ben */ #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <iostream> #include <algorithm> #include <queue

UVA 10976 Fractions Again?! 简单枚举题

#include<stdio.h> struct pairs{ int x,y; }; struct pairs pairs[10000]; int judge(int k,int i){ if((k*i)%(i-k)==0) return 1; else return 0; } int main(){ int k,count; while(scanf("%d",&k)!=EOF){ count=0; for(int i=k+1;i<=2*k;i++){ if