小強有n個養雞場,第i個養雞場初始有a[i]只小雞,小強的每個養雞場每天早上都會增加k只小雞,到了下午小強會把雞最多的雞場賣掉一半雞,那麼小強想知道m天後他所有養雞場一共有幾隻雞。
第一行輸入三個正整數n,m,k;
第二行輸入n個正整數a[i]表示養雞場雞數量。
1<=n<=100000, 1<=m<=100000
1<=k<=10000, 1<=a[i]<=100000
輸出乙個整數表示答案。
樣例:輸入
3 3 100
100 200 400
輸出925
所有的雞場每天會增加k隻雞,我們不妨把雞場分成兩間屋子,一間屋子裝原來的雞a[i],一間屋子裝新增的雞k,每個養雞場新增的雞的數量都是一樣的,假如現在是第1天,第now號養雞場有最多雞,那麼需要賣掉(a[now]+k)/2隻雞,我們假設只賣第一間屋子的雞,那麼兩個屋子的雞數量變成了a[now]-(a[now]+k)/2和k,而其他雞場兩個屋子的雞數量是a[i]和k,比較大小的時候我們可以不需要比較第二間屋子的雞,因為所有雞場第二間屋子的雞數量都一樣,按照這個思路,每天只需要取第一間屋子雞最多的那個養雞場,然後a[now] = a[now]-(a[now] + x*k)/2
,這裡x是指第x天,第二間屋子有x*k
隻雞了,為了方便取第一間屋子最大的雞數量,我們把原雞場的雞數量放進乙個優先佇列當中,每天進行一次pop最大雞數量和push賣完剩下的雞數量。雞的總數為所有雞場第一間屋子+第二間屋子,這裡第二間屋子第m天總共有n*m*k
隻雞,第一間屋子總共有的就是佇列裡面的值相加。
#include
#include
#include
#include
using
namespace std;
intmain()
for(
int i =
1; i <= m; i++
)long
long sum =0;
while
(!que.
empty()
) cout << sum + n*m*k << endl;
return0;
}
小強得到了乙個長度為n的序列,他想隨機選擇這個序列的乙個連續子串行,並求出這個序列的最大值,請你告訴他這個最大值的期望是多少?
輸入第一行n表示序列長度,1<=n<=10^6;
第二行為n個正整數,每個數字不超過10^5。
輸出這個最大值的期望,保留六位小數。
樣例:輸入
31 2 3
輸出2.333333
期望是指所有連續子串行的最大值相加除以連續子串行數量,乙個序列有多少連續子串行呢?假如序列長度為n,那麼長度為1的連續子串行有n個,長度為2的連續子串行有n-1個…所以一共有n*(n+1)/2
個連續子串行,那我們把所有的連續子串行求出來然後把最大值相加?顯然很不合理,複雜度爆表,換乙個思路,如果以當前這個數字為最大值,哪些序列是滿足的?先往左找到左邊界再往右找到右邊界,例如4 1 2 3 2 1 4如果以3為最大值,滿足的範圍是1 2 3 2 1,滿足的子串行是1 2 3,1 2 3 2,1 2 3 2 1,2 3,2 3 2,2 3 2 1,3,3 2,3 2 1共九個,實際可以用兩個變數來計數,乙個記左邊有幾個數,乙個記右邊有幾個數,上面的例子左邊是1 2 3三個數,右邊是3 2 1三個數,一共有3*3=9種排列方式。這樣我們遍歷一遍就可以得到期望的分子,再除以數量即可。
#include
#include
#include
using
namespace std;
intmain()
long
long m = n*
(n+1)/
2;cout <<
1.0*sum/m << endl;
return0;
}
但是存在一些問題,比如 3 1 3,在計算第乙個3的時候會用到313序列,第二個也會用到,重複計算了,那麼我們把判斷大小的等於號只取左邊不取右邊,也就是
while
(i-l >=
0&& num[i-l]
<= num[i]
) l++
;while
(i+r < n && num[i+r]
< num[i]
) r++
;
這樣就避免了重複。
複雜度可能還是不足,但是筆試一小時的情況下也只能處理成這樣了。
最近正好學習了單調棧,對於求解這種左右邊界十分方便,所以重新修改了一下**,複雜度降低。
#include
#include
#include
#include
using
namespace std;
int n, l[
1000100
], r[
1000100];
long
long num[
1000100];
intmain()
l[i]
= sta.
top()+
1;sta.
push
(i);
}while
(!sta.
empty()
) sta.
pop();
sta.
push
(n);
for(
int i = n-
1; i >=
0; i--
)long
long sum =0;
for(
int i =
0; i < n; i++
) sum +
= num[i]
*(i - l[i]+1
)*(r[i]
-i+1);
double ans =
2.0*sum /n /
(n+1);
printf
("%.6f\n"
, ans)
;return0;
}
阿里 2020暑期實習生 筆試回憶
給若干點的座標,代表每乙個村子,現在要修一條平行於y軸且無限長的水渠,求所有村莊距離這條水渠垂直長度之和的最小值。include include include include include using namespace std intmain cout minval system pause ...
微軟實習生招聘筆試題目
微軟實習生招聘筆試題目 提交材料 1.不超過2頁的說明書,包括演算法,設計,使用說明,及程式編譯執行環境要求 2.c c 或c程式源 程式必須是可執行的 3.optional visual studio project 檔案,以及其他編譯必須檔案 4.請在截止時間11月30日 週日 前交卷 含週日當...
騰訊2012實習生招聘筆試題
由此觀之,基本上我知道的錯誤率就會很小。像基本的資料結構與演算法。但是不知道的錯誤率接近100 了,比如作業系統 資料庫 linux 設計模式的題。但是這些題其實也是很基礎的,與考研題類似,甚至還沒有達到考研題的難度。但是現在主要是攻破c 語言和資料結構與演算法的堡壘,其他型別的題目只能等後期 建設...