luogu P1984 [SDOI2008]烧水问题

原题链接:https://www.luogu.org/problem/show?pid=1984

本题的思路其实很好想,那就是对于每一杯未烧开的水,在单独加热它之前,先用之前的杯子与其进行能量均分,直到之前的杯子全部用过一遍,这杯水能达到的温度已经是最高了,想要其烧开就只能加热它了。

然而这样的做法,会有两个问题

1.复杂度:很明显,每一杯水都要遍历之前的各杯,这样的做法复杂度为n^2,而此题n<=50000,可能会超时。

2.精度问题:如果用s来表示每杯水的温度,在与其他杯子进行热量交换时,会有很多/2的操作,而double虽然很好,但是计算次数多了也难免会出现精度问题。

手动计算出每杯水需要加热的温度在100度中占的比例,s1=1,s2=1/2,s3=3/8,s4=5/16,s5=35/128;

似乎没什么规律。但是当用后一项除前一项之后,就得到了这么一个结果

s2/s1=1/2,s3/s2=3/4,s4/s3=5/6,s5/s4=7/8

按照这个规律,s6/s5=9/10,手动模拟计算,确实是此结果,

于是归律便找到了,一次循环即可解决问题,记录(当前的水加热的比例)/(上一杯水加热的比例)的比值,计算出结果,加进答案中即可

#include<cstdio>
double n,a=-1,b,ans=1,s=1,t=1;
int main()
{
    scanf("%lf",&n);
    for(int i=2;i<=n;i++)
    {
        a+=2,b+=2;
        s*=(a/b);
        ans+=s;
//        printf("%lf %lf
",s,ans);
    }
    printf("%.2lf",(ans/n)*420000);
    return 0;
}
原文地址:https://www.cnblogs.com/zeroform/p/7679766.html