原题链接: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\n",s,ans); } printf("%.2lf",(ans/n)*420000); return 0; }
原文:http://www.cnblogs.com/zeroform/p/7679766.html