UVA 10137(截取精度)和UVA11300(中位数)

先在白书上看了这个题目UVA11300,多有意思的推导

题目大意:给出一个整数n 然后n个人的钱。n个人围着一个圆桌
每个人可以给旁边的人钱。最终的目的是所有人的钱一样多。数据保证可以实现。
每有一个人给别人一块钱就是步数加一 现在要最少的步数实现。
最终每个人的钱数假设为M=tot/n;
每个人开始有的钱为Ai;
Ci表示Ai-M
这个题就是中位数的距离思想 n个人逆时针标号1-n
首先用x1表示1号给n号的钱的数量
同理x2表示2号给1号的钱
那么我么可以列等式
对于每个人 i Ai-xi+xi+1=M 就是说原来有的钱减去他给钱一个的钱加上后一个给他的钱等于M
我们可以得出 x2 = M-A1+x1 =x1-C1;
             x3 = M-A2+x2 = x2-c2 =x1-c1-c2;
     .........


我们最终希望的是x1 +x2 +xn的绝对值最小 也就是说
|x1| +|x1-c1| + |x1-c1-c2| +.....+|x1-cn-1| 最小


也就是 这n个点距离x1 的距离的绝对值最小。

这个点应该是中位数!,对没错,具体证明见白胖书

代码




#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
long long a[1000005],c[1000005];
int main()
{
    int n,i;
    long long sum=0,x_1,m;
    while(scanf("%d",&n)!=EOF)
    {
        sum=0;
        for(i=0;i<n;i++)
        {
            scanf("%lld",&a[i]);
            sum+=a[i];
        }
        m=sum/n;c[0]=0;
        for(i=1;i<n;i++)
            c[i]=a[i]+c[i-1]-m;
        sort(c,c+n);
        x_1=c[n/2];
        long long ans=0;
        for(i=0;i<n;i++)
        ans+=abs(x_1-c[i]);
        printf("%lld\n",ans);
    }
    return 0;
}



同时又做到了一题:

UVA10137

当时笔算第二个怎么都等于12.00= =,原来美元精确到分是小数点后两位,每次都是截取的小数点后2位,不进位的。

现在分析,由于没有位置限制,一定是由“高能量”流向“低能量”,最后守恒。

这道题其实让我学习了,精度的截取:

sprinft(tmp,"%k.lf",ans);

sscanf(tmp,"%lf",&ans);



#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;

double a[1005];
 char  tmp[1010];
int main()
{
    int n,i;
    double sum=0,ave;
    while(scanf("%d",&n)!=EOF&&n)
    {
        sum=0;
        for(i=1;i<=n;i++)
        {scanf("%lf",&a[i]);
          sum+=a[i];
        }
        ave=sum/n;
        sprintf(tmp,"%.2lf",ave);
        sscanf(tmp,"%lf",&ave);
        double ans1=0,ans2=0;

        for(i=1;i<=n;i++)
        {
           if(a[i]>ave)
           ans1 += (a[i]-ave);
           else
           ans2 += (ave-a[i]);

        }
        if(ans1>ans2)
        printf("$%.2lf\n",ans2);
        else
        printf("$%.2lf\n",ans1);
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值