標籤:面積 正整數 初學 noip 應該 namespace 小數 include 需要
Task 1.紙殼子(box.pas/box.c/box.cpp)【題目描述】Mcx是一個有輕度潔癖的小朋友。有一天,當他沉溺於數學卷子難以自拔的時候,恍惚間想起在自己當初學習機率的時候準備的一堆橡皮還雜亂地堆在自習室裡。這顯然是他無法容忍的。於是他決定做一個體積為V(V=abc)的紙盒子,以便能整齊的擺放它們。為了簡單起見,這個紙盒子的長、寬、高均為正整數。當然了,Mcx是一個以勤儉聞名的小朋友,因此他想知道,這個紙盒子的表面積(S=2ab+2ac+2bc)的最小值是多少呢?【題目輸入】僅一行,為一個正整數V,表示紙盒子的體積。【題目輸出】僅一行,為一個正整數S,表示紙盒子的最小表面積。【範例輸入1】17【範例輸出1】70【範例輸入2】146【範例輸出2】442【範例解釋】對於體積為17的盒子只有一種製作方法就是長1寬1高17(這裡我們可以認為長,寬,高是等價的),於是它的最小表面積就是2*1*17+2*1*17+2*1*1 = 70【資料範圍】30%資料滿足V<=1000100%資料滿足V<=10^9分析:首先!這是一道!數學題!!數學題就要有數學題的樣子//這道要比其他數論妖豔賤貨題好多了。這道題其實沒有什麼高深的解法。但是想一想其實就是枚舉。枚舉a,枚舉b之後c就自然就出來了。而剛才的方法,瞎基本搞,小資料應該可以拿分。第一種最佳化就是枚舉a的時候只需要枚舉a<=pow(v , 1.0/3 );只枚舉前面的。而b就用枚舉b<=sqrt(v/a);c直接就可以求出。當然還要對它進行是不是整數的判斷。第二種最佳化就是枚舉a的時候。對是否枚舉b的剪枝判斷。我們知道因為在枚舉a的時候。v與a就是定值。表面積公式就是2*(ab+bc+ac)就改變成了2*(v/a+a*(b+c)) 而表面積的最小值,就轉變成了(b+c)的最小值。我們又知道v/a==bc 那麼 bc 也是定值 所以當b==c的時候是理論最小值。所以我們如果求出的理論最小值都要比我們枚舉出來的a的答案大。那我們就沒有必要再去枚舉b。為什麼b*c為一定的時候 當b==c 時 (b+c)最小呢?這裡特別感謝數競大爺的講解:
貼出代碼:
#include<cstdio>#include<algorithm>#include<cmath>using namespace std;int main(){ freopen("box.in","r",stdin); freopen("box.out","w",stdout); int v; long long int ans=1000000000000000LL,bmj; scanf("%d",&v); for(int a=v;a>=1;--a) { if((v/a)*a!=v)continue; int kk=sqrt(v/a); bmj=(long long int)(v/a+a*2*kk); if(bmj<=ans||a==v){ for(int b=a;b<=a+kk;++b){ int c=v/a/b; if(c*a*b!=v)continue; ans=min(ans,(long long int)a*b+(long long int)b*c+(long long int)a*c); } } } printf("%I64d",2*ans); fclose(stdin); fclose(stdout); return 0;}
noip類比賽 紙殼子