HDU 6117 打怪獸2(組合數學 優先佇列)

2021-08-07 23:12:29 字數 4420 閱讀 6643

description

度度熊在玩乙個叫做「打怪獸」的遊戲。

遊戲的規則是這樣的。

度度熊一開始會有乙個初始的能量值。每次遇到乙個怪獸,若度度熊的能量值≥ 怪獸的能量值並且度度熊剩餘血量≥怪獸的攻擊力,那麼怪獸將會被打敗,度度熊的能量值增加1,度度熊的血量減少該怪獸的攻擊力,否則度度熊死亡(度度熊的血量剛好減到0時並不會死亡,還能繼續戰鬥),遊戲結束。

若怪獸全部打完,遊戲也將會結束。

共有n個怪獸,由於度度熊比較弱,它一開始只有1點能量值。

n個怪獸排列隨機,也就是說共有n!種可能,度度熊想知道結束時它能量值的期望。

注意這裡怪獸的編號是從1開始到編號n為止且編號為i的怪獸能量值為i-1。

由於小數點比較麻煩,所以你只需要輸出期望*n!關於1000000007取模後的值就可以了!

在樣例中有5個怪獸,它們的能量分別為0,1,2,3,4,其中每個怪獸的攻擊力都為1。

input

多組資料。對於每一組資料:

第一行兩個數n,m表示有n只怪獸,度度熊的初始血量(1<=n<=500000,1<=m<=10^9)。

接下來一行n個數ai表示編號為i的怪獸的攻擊力(0<=ai<=m)。

output

一行表示答案。

sample input

5 4

1 1 1 1 1

sample output

solution

num[

i]為至少乾掉

i 只怪獸的方案數,則乾掉

i只怪獸的方案數為nu

m[i]

−num

[i+1

] 進而

ans=

∑i=1

n−1i

⋅(nu

m[i]

−num

[i+1

])+n

um[n

]=∑i

=1nn

um[i

] 考慮求nu

m[i]

,給怪獸編號為

0 ~n−

1,那麼第

i 只怪獸能量為

i攻擊力為ai

,如果要乾掉

i 個怪獸,那麼0~

i−1 這

i 個怪獸中至少要乾掉i−

1個,由於第

i 次乾掉的怪獸其編號最多是

i,故我們考慮編號為

0 ~

i的怪獸即可

1 .若m−

∑j=0

i−1a

j≥0且

m−∑j

=0ia

j≥0 ,那麼前i+

1 只怪獸都可以乾掉,第

1 次可以從前兩個中選乙個乾掉,第

2次可以從前三個中(除去第一次被乾掉的還剩兩個)選乙個乾掉,第

i 次可以從前i+

1個中(除去前i−

1 次乾掉的還剩兩個)選乙個乾掉,故從前i+

1 個怪獸中選出

i 個乾掉方案數是2i

,剩下的n−

i 個怪獸可以隨便放,總方案數2i

⋅(n−

i)!

2.若m−

∑j=0

i−1a

j≥0且

m−∑j

=0ia

j<

0 ,那麼前i+

1 只怪獸不能像第

1 種情況那樣每次隨便乾掉,如果要乾掉

i個,那麼就要有一些「大怪獸」不能被乾掉,否則完不成乾掉

i 只怪獸的任務,假設m−

∑j=0

iaj+

ak>=

0,說明如果不乾掉第

k 只怪獸的話剩下的

i只怪獸都可以乾掉,即可以乾掉編號為

0 ~k−

1和k+

1 ~

i 的這些怪獸,從0~

k−1 的這

k 只怪獸中選出k−

1只怪獸乾掉的方案數和第

1 種情況相同,方案數為bk

=2ma

x(注意k=

0 時方案數是1),剩下乙隻怪獸只能第

k 次乾掉,乾掉這

k只怪獸後能量值是k+

1 ,第k+

1 步就只能乾掉k+

1 ,第k+

2 步就只能乾掉k+

2 ,……,第

i 步只能乾掉

i,故乾掉編號為

0 ~k−

1和k+

1 ~

i 的這些怪獸的方案數為bk

,剩下的n−

i 只怪獸依舊可以隨便放,令su

m=∑k

=0i[

m−∑j

=0ia

j+ak

≥0]b

k ,則總方案數為su

m⋅(n

−i)!

3 .若m−

∑j=0

i−1a

j<

0,類似第

2 種情況,令su

m=∑k

=0i[

m−∑j

=0ia

j+ak

≥0]b

k,則總方案數為su

m⋅(n

−i)!

現在問題變成如何快速得到su

m ,即滿足m−

∑j=0

iaj+

ak≥0

的bk 之和,注意到隨著

i 的增大,m−

∑j=0

iaj是遞減的,所以滿足條件的

k 只會越來越少,第一次出現滿足條件的

k是在第

2 種情況發生時,而且顯然第

2種情況至多出現一次,之後滿足條件的

k 中,一些ak

值較小的會被淘汰掉,用優先佇列維護滿足條件的

k ,ak

值最小的在隊首,維護su

m 的值,在第

2 種情況出現時把所有滿足條件的

k值放入優先佇列中並累加bk

的值得到su

m ,之後都是第

3 種情況,每次從隊首不斷取出不滿足條件的

k值,把bk

值從su

m 中減掉,這樣每個

k 值入隊一次出隊一次,每次計數是o(

1)的,總時間複雜度是o(

nlog

n)

注意上面只求了nu

m[1]

~num

[n−1

] ,對於nu

m[n]

,如果m−

∑i=0

n−1a

i≥0 ,說明這

n 只怪獸可以隨便乾掉,由第

1種情況,乾掉前n−

1 只怪獸每次都有

2 種方案,最後剩乙隻沒別的選擇,故nu

m[n]

=2n−

1,否則nu

m[n]

=0

code

#include

#include

#include

#include

using namespace std;

typedef long

long ll;

namespace fastio

}return *p1++;

}inline bool blank(char ch)

inline void read(int &x)

inline void readlld(ll &x)

#undef buf_size

};using namespace fastio;

#define mod 1000000007

#define maxn 500005

int n,a[maxn],f[maxn],p2[maxn];

ll m;

struct node

};priority_queueque;

int main()

ans+=(ll)sum*f[n-i]%mod;

if(ans>=mod)ans-=mod;

}else

);sum+=p2[max(0,j-1)];

if(sum>=mod)sum-=mod;

}ans+=(ll)sum*f[n-i]%mod;

if(ans>=mod)ans-=mod;

}else }}

if(m>=0)

printf("%d\n",ans);

}return

0;}

HDU 5698 組合數學

傳送門 計算走i步的方法數 走i步 可以分解為在x方向上走的 x1,x2,xi 在y1,y2,yi 步 就是將 n 1分解為i的不為0的數,就相當於在n 2個空裡插入i 1個版 將 m 1 分解為i個不為0的數 也就是 c n 2,i 1 c m 2,i 1 總數也就是sum c n 2,i 1 c...

hdu 6143 組合數學 dp

題意 m個字母,組成兩個長度為n的字元,其中乙個字母不能同時出現在兩個串中。問總方案?思路 列舉m個中恰好有i個在第乙個串,有j個在第二個串。然後求個和。具體其中n個空恰好k種顏色,可以用dp預處理。dp j i dp j 1 i i mod dp j 1 i 1 i mod mod include...

hdu 5106 組合數學 找規律

給定n和r,要求算出 0,r 之間所有n onebit數的和,n onebit數是所有數字中1的個數。對於乙個n bit數,可以根據與r最高不同位的位置分成幾類。比如r 100100010,可以分成0 xx,1000 xx,10010000x三類。x處可任取0或者1。x的個數為n,x中1的個數為k。...