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-;
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 简单枚举+精度处理的更多相关文章
- UVA - 10167 - Birthday Cake (简单枚举)
思路:简单枚举 AC代码: #include <cstdio> #include <cstring> #include <iostream> #include &l ...
- Java练习 SDUT-1959_简单枚举类型——植物与颜色
简单枚举类型--植物与颜色 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 请定义具有red, orange, yell ...
- zoj 3356 Football Gambling II【枚举+精度问题】
题目: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3356 http://acm.hust.edu.cn/vjudge/ ...
- zoj 1622 Switch 开关灯 简单枚举
ZOJ Problem Set - 1622 Switch Time Limit: 2 Seconds Memory Limit: 65536 KB There are N lights i ...
- UVa 725 简单枚举+整数转换为字符串
Division Write a program that finds and displays all pairs of 5-digit numbers that between them use ...
- UVA 725 UVA 10976 简单枚举
UVA 725 题意:0~9十个数组成两个5位数(或0开头的四位数),要求两数之商等于输入的数据n.abcde/fghij=n. 思路:暴力枚举,枚举fghij的情况算出abcde判断是否符合题目条件 ...
- 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 ...
- hdu5258简单枚举
百度之星复赛第一题.不明白这么水的题为何一堆人没过...这些人是咋晋级复赛的呢... /* * Author : ben */ #include <cstdio> #include < ...
- C#枚举的简单使用
枚举这个名词大家都听过,很多小伙伴也使用过, 那么枚举在开发中能做什么,使用它后能给程序代码带来什么改变,为什么用枚举. 各位看官且坐下,听我一一道来. 为什么使用枚举? 1.枚举能够使代码更加清晰, ...
随机推荐
- lintcode :reverse integer 颠倒整数
题目: 颠倒整数 将一个整数中的数字进行颠倒,当颠倒后的整数溢出时,返回 0 (标记为 32 位整数). 样例 给定 x = 123,返回 321 给定 x = -123,返回 -321 解题: 直接 ...
- vlc/ffmepg/mplayer/gstreamer/openmax/mpc/ffdshow/directshow
一些应该学习的开源框架与库用途和差别 一.播放器层次 这个层次上,是直接可以用的软件,已经做完了一切工作,如果我们需要用他们,是不需要写一行代码的,编译通过就可以拿来使用了,对于国内这些山寨公司来说, ...
- PCB电路板上防潮绝缘抗腐蚀的三防漆
三防漆(Conformal Coating)是一种涂在电路板上以形成保护膜的方法,这层保护膜通常仅是薄薄的一层(约30-210µm),它可以用来加强电子产品的防潮.防污.防尘.防化学污染的能力,也可以 ...
- GitHub最全的前端资源汇总仓库(包括前端学习、开发资源、求职面试等)
在GitHub上收集的最全的前端资源汇总(包括前端学习.前端开发资源.前端求职面试等) 个人结合github上各位大神分享的资源进行了简单的汇总整理,每一个条目下面都有丰富的资料,是前端学习.工作的好 ...
- linux shell 命令学习(1) du- estimate file space usage
du - estimate file space usage , 计算文件的磁盘大小 语法格式: du [OPTION] ... [FILE] 描述: 汇总每个文件的磁盘大小, 递归汇总目录的大小, ...
- swift:类型转换(is用作判断检测、as用作类型向下转换)
类型转换是一种检查类实例的方式,并且哦或者也是让实例作为它的父类或者子类的一种方式. 类型转换在Swift中使用is 和 as操作符实现.这两个操作符提供了一种简单达意的方式去检查值的类型或者转换 ...
- 基于Jws的WebService项目
基于Jws的WebService项目 1.服务器端建立 1.1.创建接口 [java] view plaincopy @WebService public interface IWebServi ...
- List应用举例
1.集合的嵌套遍历 学生类: package listexercise; /** * Created by gao on 15-12-9. */ public class Student { priv ...
- 自定义View(3)关于canas.drawText
本文以Canvas类的下面这个函数为基础,它用来在画布上绘制文本. public void drawText(String text, float x, float y, Paint paint) 效 ...
- Android Studio设备背景色
从eclipse转到Android Studio. Android Studio的一些设置 1.设置字体大小:Settings->Editor->Colors&Fonts-> ...