其实这题还是挺简单的,因为移动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-;
int get_int() {
int res = , ch;
while (!((ch = getchar()) >= '' && ch <= '')) {
if (ch == EOF)
return << ;
}
res = ch - '';
while ((ch = getchar()) >= '' && ch <= '')
res = res * + (ch - '');
return res;
}
//输入整数(包括负整数),用法int a = get_int2();
int get_int2() {
int res = , ch, flag = ;
while (!((ch = getchar()) >= '' && ch <= '')) {
if (ch == '-')
flag = ;
if (ch == EOF)
return << ;
}
res = ch - '';
while ((ch = getchar()) >= '' && ch <= '')
res = res * + (ch - '');
if (flag == )
res = -res;
return res;
}
const int MAXN = ;
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 > ) {
su -= sum[s - ];
}
double ret = su / (e - s + 1.0);
return ret;
} void comput(int s, int e, double c) {
double ret = ;
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 = ;
for (int i = ; i < N; ) {
ret += (data[i] - c) * (data[i] - c) * ndata[i];
i += ndata[i];
}
return ret;
} void work() {
double cen = getCenter(, N - );
// printf("cen = %f\n", cen);
ans = comput(cen);
for (int a = K; a >= ; a--) {
if (ans < eps) {
break;
}
int e = N + a - K - ;
double tmpc = getCenter(a, e);
comput(a, e, tmpc);
}
} void treat() {
for (int i = ; i < N; i++) {
int d = data[i];
int j = i + ;
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 = ; i < N; i++) {
data[i] = get_int2();
}
sort(data, data + N);
treat();
sum[] = data[];
for (int i = ; i < N; i++) {
sum[i] = sum[i - ] + data[i];
}
work();
printf("%.10lf\n", ans);
}
return ;
}

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

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

 /*
* 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 <cctype>
using namespace std;
typedef long long LL;
const double eps = 1e-;
const int MAXN = ;
int N, K;
LL data[MAXN], sum[MAXN], sum2[MAXN];
double ans;
int get_int() {
int res = , ch;
while (!((ch = getchar()) >= '' && ch <= '')) {
if (ch == EOF)
return << ;
}
res = ch - '';
while ((ch = getchar()) >= '' && ch <= '')
res = res * + (ch - '');
return res;
} //输入整数(包括负整数),用法int a = get_int2();
int get_int2() {
int res = , ch, flag = ;
while (!((ch = getchar()) >= '' && ch <= '')) {
if (ch == '-')
flag = ;
if (ch == EOF)
return << ;
}
res = ch - '';
while ((ch = getchar()) >= '' && ch <= '')
res = res * + (ch - '');
if (flag == )
res = -res;
return res;
}
inline LL getSum(int from, int to) {
LL ret = sum[to];
if (from > ) {
ret -= sum[from - ];
}
return ret;
} inline LL getSum2(int from, int to) {
LL ret = sum2[to];
if (from > ) {
ret -= sum2[from - ];
}
return ret;
} inline double getCenter(int s, int e) {
LL su = sum[e];
if (s > ) {
su -= sum[s - ];
}
double ret = su / (e - s + 1.0);
return ret;
} inline double comput(int s, int e, double c) {
LL s1 = getSum(s, e);
LL s2 = getSum2(s, e);
double ret = s2 + (e - s + 1.0) * c * c - 2.0 * c * s1;
return ret;
} void work() {
double cen = getCenter(, N - );
ans = comput(, N - , cen);
for (int a = ; a <= K; a++) {
int e = N + a - K - ;
double tmpc = getCenter(a, e);
double ret = comput(a, e, tmpc);
if (ret < ans) {
ans = ret;
}
}
} int main() {
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
#endif
int T= get_int();
while (T--) {
N = get_int();
K = get_int();
for (int i = ; i < N; i++) {
data[i] = get_int2();
}
if (K == N || N - == K) {
printf("0\n");
continue;
}
sort(data, data + N);
sum[] = data[];
sum2[] = data[] * data[];
for (int i = ; i < N; i++) {
sum[i] = sum[i - ] + data[i];
sum2[i] = sum2[i - ] + data[i] * data[i];
}
work();
printf("%.10lf\n", ans);
}
return ;
}

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

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

    思路:简单枚举 AC代码: #include <cstdio> #include <cstring> #include <iostream> #include &l ...

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

    简单枚举类型--植物与颜色 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 请定义具有red, orange, yell ...

  3. zoj 3356 Football Gambling II【枚举+精度问题】

    题目: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3356 http://acm.hust.edu.cn/vjudge/ ...

  4. zoj 1622 Switch 开关灯 简单枚举

    ZOJ Problem Set - 1622 Switch Time Limit: 2 Seconds      Memory Limit: 65536 KB There are N lights i ...

  5. UVa 725 简单枚举+整数转换为字符串

    Division  Write a program that finds and displays all pairs of 5-digit numbers that between them use ...

  6. UVA 725 UVA 10976 简单枚举

    UVA 725 题意:0~9十个数组成两个5位数(或0开头的四位数),要求两数之商等于输入的数据n.abcde/fghij=n. 思路:暴力枚举,枚举fghij的情况算出abcde判断是否符合题目条件 ...

  7. uva 10976 Fractions Again(简单枚举)

    10976 Fractions Again It is easy to see that for every fraction in the form 1 k (k > 0), we can a ...

  8. hdu5258简单枚举

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

  9. C#枚举的简单使用

    枚举这个名词大家都听过,很多小伙伴也使用过, 那么枚举在开发中能做什么,使用它后能给程序代码带来什么改变,为什么用枚举. 各位看官且坐下,听我一一道来. 为什么使用枚举? 1.枚举能够使代码更加清晰, ...

随机推荐

  1. hdu 4447 Yuanfang, What Do You Think?

    思路: 这题有个结论也可以自己归纳: 对于给定的n,其约数用pi表示 T(n)=T(p1)T(p2)……T(pn)T(n') 其中T(n')是这个式子所独有的也就是 T(n')=(x^n-1)/T(p ...

  2. HTTP 408请求超时错误解决办法

    错误描述 对于大多数网站而言,我们所看到的错误消息已经是开发者定制过的页面,比如我们最常见的自定义404错误页面,一般而言,我们看到的408错误应该是类似这样的提示:“408:Request Time ...

  3. Project Euler 89:Roman numerals 罗马数字

    Roman numerals For a number written in Roman numerals to be considered valid there are basic rules w ...

  4. lintcode :Ugly Numbers 丑数

    题目 丑数 设计一个算法,找出只含素因子3,5,7 的第 k 大的数. 符合条件的数如:3,5,7,9,15...... 样例 如果k=4, 返回 9 挑战 要求时间复杂度为O(nlogn)或者O(n ...

  5. php相关学习资源

    相关书籍资源: 1:PHP和MySQL Web开发 经典书籍 视频教程: PHP开发工程师闯关记--初识PHP php调试技巧: PHP 程序员的调试技术 使用 print 语句.错误报告和 PHPE ...

  6. java:打包

    包名命名规范: 1.包名全部小写 2.包名一般情况下是域名的倒过来写+个性命名,如:tinyphp.com,就写成com.tinyphp+.xxx 打包方法 package + 包名 package ...

  7. MSRA面试总结

    http://blog.renren.com/share/405984844/16014442499 注:以下内容纯凭记忆,由于已经过去一个多月,不保证准确性.由于面试前没有签保密协议,本文透露了比较 ...

  8. .Net MVC API初试

    新建.net mvc api项目后,直接运行,默认会访问http://localhost:xxxx/Home/Index页面,这个页面不是要访问的API页面. 从项目的目录可以看出,默认的API页面访 ...

  9. html5 touch事件实现触屏页面上下滑动(二)

    五一小长假哪都没去,睡了三天,今天晕晕沉沉的投入工作了,但还是做出了一点点效果 上周用html5的touch事件把简单的滑动做出来了,实现了持续页面上下滑动的效果,参考之前 的文章及代码html5 t ...

  10. $.post()

    定义和用法 post() 方法通过 HTTP POST 请求从服务器载入数据. jQuery.post(url,data,success(data, textStatus, jqXHR),dataTy ...