题意

有一个含有\(2n(n \leqslant2000)\)个实数的数列,取出\(n\)个向上取整,另\(n\)个向下取整。问取整后数列的和与原数列的和的差的绝对值。

就是说,令\(a\)为原数列,\(b\)为取整后数列,求

\[min(abs(\sum_{i=1}^{2n}a-\sum_{i=1}^{2n}b))
\]

解题思路

刚开始大力猜了一波贪心结论,然后怒WA n发……

我也不知道怎么会想到以下这个奇怪的结论的……

如果我们设\(n\)个被向上取整的数的小数部分的和为\(a\)(其中本来为整数的有\(x\)个),设\(n\)个被向下取整的数的小数部分的和为\(b\)。那么答案就是\(ans=abs(b-(n-a-x))=abs(b+a-n+x)\)。同时我们注意到,原数列中所有数的和为\(sum=a+b\),所以呢,就有\(ans=abs(sum-n+x)\)。

这,个,东,西,和,\(a\),\(b\),没,有,关,系!!!

然后容易发现\(max(0,n-x)\leqslant x \leqslant min(n,x)\)。所以就容易得出答案了!

参考程序

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int Maxn = 2010;
double a[ Maxn << 1 ];
int n, t;//t就是上面说的x
double sum, ans; int main() {
scanf( "%d", &n );
for( int i = 1; i <= n * 2; ++i ) scanf( "%lf", &a[ i ] );
for( int i = 1; i <= n * 2; ++i )
if( a[ i ] - floor( a[ i ] ) <= 1e-18 ) t++;
for( int i = 1; i <= n * 2; ++i ) sum += a[ i ] - floor( a[ i ] );
ans = 1e9;
for( int i = max( 0, t - n ); i <= min( n, t ); ++i )
ans = min( ans, abs( sum - n + i ) );
printf( "%.3lf\n", ans );
return 0;
}

最新文章

  1. OpenCASCADE Interpolation - Lagrange
  2. LeetCode Coin Change
  3. Unity3d《Shader篇》变胖
  4. PLSQL_低效SQL的识别和查询汇总(案例)
  5. 父元素onmouseover触发事件在父子元素间移动不停触发的问题
  6. Oracle dblink 使用详解
  7. 警告&quot;Local declaration of &#39;XXX&#39; hides instance variable&quot;原因
  8. YY语音从4.0版本开始是基于Qt的开发过程,以及碰到的问题
  9. UVA 1001 Say Cheese
  10. Strata 2014 上的 AzureCAT 粉笔会谈
  11. 【功能代码】---2.patchca生成验证码
  12. Linux的DNS配置1-DNS入门
  13. shiro源码篇 - shiro的session创建,你值得拥有
  14. canvas资料
  15. JavaScript基础三
  16. ROLAP、MOLAP和HOLAP区别
  17. ES6 Generator 异步编程解决方案&amp;&amp;&amp;promise
  18. windows下使用gethostbyname函数报错无法解析的外部符号
  19. fastcgi vc6.0demo
  20. C#6.0语言规范(十九) 文档注释

热门文章

  1. 三维数点的CDQ分治板子
  2. SQL学习(一)之简介
  3. Mysql学习(三)之数据库管理工具Navicat
  4. 【electronjs入门教程 】electronjs 介绍
  5. 帝国cms 遍历某个父栏目下所有的子栏目
  6. vue--支付宝支付
  7. TVM:一个端到端的用于开发深度学习负载以适应多种硬件平台的IR栈
  8. DiffUtil和LiveData使用时遇到的问题
  9. 仿造email后缀搜索功能(2)
  10. Delphi MaskEdit 组件