【學術篇】燒水問題 打表找規律做法

md打表題.
按照貪心原則, 只要有燒開過的, 能熱傳遞就熱傳遞(反正沒有熱量損失)
所以我們只需要按照以下流程圖(唉這個圖要是崩了別埋怨我, 我也不想的嘛←_←)做即是最優解:

Created with Raphaël 2.1.0開始s=0,i=1i<=ns=s+(4200*(100-T[i])/n)For j=i+1..n:T[i]=T[j]=(T[i]+T[j])/2輸出s結束yesno

然後就得到了一個O(n2) 的做法.
顯然無法通過此題.
但是我們可以打表得到一個數列… 前幾項差不多長這樣…

420000,315000,262500,229687.5,206718.75,189492.1875,175957.03125,164959.716796875

然後找規律即可.

根據所學數列相關知識, 我們認爲這些項之間的差/比應該會有一定的關係…
但是不管是差一下還是比一下都找不出什麼顯而易見的規律…
我們發現燒水的時候是有/n 這種操作的..
我們就n 逆回去再看..
我們便可以設數列{Bi} , 滿足Bi=isi ..
然後再比就比出規律了..
發現Bi+1Bi=2i+12i=1+12i=si+1(i+1)sii ..
我們就可以化簡出O(n) 的遞推式si+1=(1+12i)siii+1
然後這樣已經足以通過此題了..

#include <cstdio>
int main(){
    int n;scanf("%d",&n);
    double s=420000;
    for(int i=1;i<n;++i)
        s=((1+1.0/(i+i))*s*i)/(i+1);
    printf("%.2lf",s);
}

但是式子長得不是很好看..太囉嗦..
我們可以收拾一下?
si+1=sii+0.5i+1
然後加上一點點奇怪的壓行技巧..就會出現warning...
就可以做成這樣

#include <cstdio>
main(){double n,s=4.2e5,i=1;scanf("%lf",&n);for(;i<n;)s*=(i+0.5)/++i;printf("%.2lf",s);}

我應該是做不到更短了…

打表題做起來應該很愉快纔對~OvO

發佈了72 篇原創文章 · 獲贊 17 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章