Description
把总质量为1kg的水分装在n个杯子里,每杯水的质量均为(1/n)kg,初始温度均为0℃。现需要把每一杯水都烧开。我们可以对任意一杯水进行加热。
把一杯水的温度升高t℃所需的能量为(4200*t/n)J,其中,“J”是能量单位“焦耳”。如果一旦某杯水的温度达到100℃,那么这杯水的温度就不能再继续升高,此时我们认为这杯水已经被烧开。
显然地,如果直接把水一杯一杯地烧开,所需的总能量为(4200*100)J。
在烧水的过程中,我们随时可以在两杯温度不同的水之间进行热传递操作。热量只能从温度较高的那杯水传递到温度较低的那杯水。由于两杯水的质量相同,所以进行热传递操作之后,原来温度较高的那杯水所降低的温度总是等于原来温度较低的那杯水所升高的温度。
一旦两杯水的温度相同,热传递立刻停止。
为了把问题简化,我们假设:
没有进行加热或热传递操作时,水的温度不会变化。
加热时所花费的能量全部被水吸收,杯子不吸收能量。
热传递总是隔着杯子进行,n杯水永远不会互相混合。
热传递符合能量守恒,而且没有任何的热量损耗。
在这个问题里,只要求把每杯水都至少烧开一遍就可以了,而不要求最终每杯水的温度都是100℃。我们可以用如下操作把两杯水烧开:先把一杯水加热到100℃,花费能量(4200*100/2)J,然后两杯水进行热传递,直到它们的温度都变成50℃为止,最后把原来没有加热到100℃的那杯水加热到100℃,花费能量(4200*50/2)J,此时两杯水都被烧开过了,当前温度一杯100℃,一杯50℃,花费的总能量为(4200*75)J,比直接烧开所需的(4200*100)J少花费了25%的能量。
你的任务是设计一个最佳的操作方案使得n杯水都至少被烧开一遍所需的总能量最少。
Input
包含多组测试数据。每组测试数据输入只有一个整数n。(1<=n<=50000)
Output
每组测试数据输出占一行。输出n杯水都至少被烧开一遍所需的最少的总能量,单位为J,四舍五入到小数点后两位
Sample Input
2
Sample Output
315000.00
分析:题目的输入为一个数n,输出也为一个数,很可能涉及到递推或数学公式。通过计算,我们可知,第一杯水所需热量(4200*100)/n,第二杯(4200*50)/n,第三杯(4200*37.5)/n,第四杯(4200*31.25)/n……==>cost2 = 1/2cost1、cost3 = 3/4cost2、cost4= 5/6cost3 ==> cost(i) = cost(i-1)*((2*i-1)/(2*i))。
参考代码
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<map>
using namespace std;
int n;
int main()
{
while( ~scanf("%d",&n))
{
double cost = (4200*100.0)/n;
double ans = cost;
for( int i = 1; i < n; i++)
{
cost *= (double)(2*i-1)/(double)(2*i);
ans += cost;
}
printf("%.2f\n",ans);
}
return 0;
}