P1984 [SDOI2008] 烧水问题
题目描述
把总质量为 1 kg1\ \rm kg1 kg 的水分装在 nnn 个杯子里,每杯水的质量均为 (1/n) kg(1/n)\ \rm kg(1/n) kg,初始温度均为 000 度。现需要把每一杯水都烧开。我们可以对任意一杯水进行加热。把一杯水的温度升高 ttt 度所需的能量为 (4200×t/n)J(4200\times t/n)\rm J(4200×t/n)J,其中,J\rm JJ 是能量单位“焦耳”。如果一旦某杯水的温度达到 100100100 度,那么这杯水的温度就不能再继续升高,此时我们认为这杯水已经被烧开。显然地,如果直接把水一杯一杯地烧开,所需的总能量为 (4200×100)J(4200\times 100)\rm J(4200×100)J。
在烧水的过程中,我们随时可以在两杯温度不同的水之间进行热传递操作。热量只能从温度较高的那杯水传递到温度较低的那杯水。由于两杯水的质量相同,所以进行热传递操作之后,原来温度较高的那杯水所降低的温度总是等于原来温度较低的那杯水所升高的温度。
一旦两杯水的温度相同,热传递立刻停止。
为了把问题简化,我们假设:
- 没有进行加热或热传递操作时,水的温度不会变化。
- 加热时所花费的能量全部被水吸收,杯子不吸收能量。
- 热传递总是隔着杯子进行,nnn 杯水永远不会互相混合。
- 热传递符合能量守恒,而且没有任何的热量损耗。
在这个问题里,只要求把每杯水都至少烧开一遍就可以了,而不要求最终每杯水的温度都是 100100100 度。我们可以用如下操作把两杯水烧开:先把一杯水加热到 100100100 度,花费能量 (4200×100/2)J(4200\times 100/2)\rm J(4200×100/2)J,然后两杯水进行热传递,直到它们的温度都变成 505050 度为止,最后把原来没有加热到 100100100 度的那杯水加热到 100100100 度,花费能量 (4200×50/2)J(4200\times 50/2)\rm J(4200×50/2)J,此时两杯水都被烧开过了,当前温度一杯 100100100 度,一杯 505050 度,花费的总能量为 (4200×75)J(4200\times 75)\rm J(4200×75)J,比直接烧开所需的 (4200×100)J(4200\times 100)\rm J(4200×100)J 少花费了 25%25\%25% 的能量。
你的任务是设计一个最佳的操作方案使得 nnn 杯水都至少被烧开一遍所需的总能量最少。
输入格式
输入数据共一行,一个整数 nnn。
输出格式
输出 nnn 杯水都至少被烧开一遍所需的最少的总能量,单位为 JJJ,四舍五入到小数点后两位。
输入输出样例 #1
输入 #1
2
输出 #1
315000.00
说明/提示
数据范围及约定
对于全部数据,1≤n≤30000001 \le n \le 30000001≤n≤3000000。
C++实现
#include<cstdio>
#include<cstring>
int n;
double ans;
int main()
{
scanf("%d",&n);
double s=420000.00/n;
for(int i=1;i<n;i++)
{
ans+=s;
s*=(double)(2*i-1)/(double)(2*i);
}
printf("%.2lf",ans+s);
return 0;
}

后续
接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容
5768

被折叠的 条评论
为什么被折叠?



