題目鏈結
很好的題目,很早就關注了此題,但一直沒看懂題解,今天在紙上模擬了很久終於了有了新的感悟
對於這種 求期望
∗n!m
od1e
9+
7求期望*n! \mod 1e9+7
求期望∗n!
mod1
e9+7
的問法實際上就是求方案數。
雖然數列完全打亂了,但其實對於二分結果的影響並沒有直觀上的那麼大。
形如下列數列:
1 2 3 4 5 6 7 8 9 10
下面讓我們來模擬二分查詢7的位置的過程:
第一次mid = 5 而因為 7 > 5 ,故右移 ⇒ l = mid+1 = 6
第二次mid = 8 而因為 7 < 5 ,故左移 ⇒ r = mid-1 = 7
第三次mid = 6 而因為 7 > 6 ,故右移 ⇒ l = mid+1 = 7
第四次mid = 7 而因為 7 == 7 故二分結束
從以上過程我們發現,我們查詢 7 的過程,實際上起作用的點只有 5,6,7,8,這些點決定了每一次二分的左移還是右移,那如果我們改變其他數的位置,形如:
1 3 4 25 6 7 89 10
或者1 2 10 45 6 7 83 9
只要不改變5,6,7,8的位置,無論其他數字置怎麼變化,結果都是一樣的。
從上面的模擬過程我們可以試著推出此題的結**式。
因為我們要求出每次二分結束後 r = k 的方案數,故我們可以模擬二分的過程,求出特殊點的個數(形如上例子5,6,7,8),由二分的性質,這樣的點一定不超過 log
nlogn
logn
個。考慮當 mid 在 k的右邊,此時我們需要左移,故必須滿足條件$ a[mid] <= m$
此時mid這個點就是乙個特殊點,因為其存在約束條件,值必須<=m
<=m
<=m
,統計此類點的個數為x,因為x個點的值各不相同且值只能在1~m之間,故則此類約束點的方案數為
c mx
c_m^x
cmx
同理,對於需要右移的點,統計其個數為y,其約束條件是其值val
valva
l滿足 m
l<=n m < val <= n ml<=n 故方案數為: c n− my c^y_ cn−my 而對於沒有約束的點,因個數為(n− x−y) (n-x-y) (n−x−y )且可以隨意排列,故方案數為(n− x−y) !(n-x-y)! (n−x−y )!綜上所述:ans =cmx ∗cn− my∗( n−x− y) !ans = c_m^x * c^y_ * (n-x-y)! ans=cm x∗c n−my ∗(n −x−y )!公式有了,只剩最後乙個關鍵點就是n的範圍有1e9,而x,y的和最多只有log (n )log(n) log(n) 也就是說我們需要求出 (1e 9) !(1e9)! (1e9)! 對於此題如果暴力時間複雜度是**的,離線預處理的話空間複雜度是**的。 此時就涉及了乙個神奇的方法,分塊打表。 我們可以將1e9 1e91e 9分成很多小的部分,比如分成一千塊的話每一部分只有1e6 1e61e 6,我們離線處理塊的值,即(1e 6)!, (2e6 )!.. .(1e 9) !(1e6)!,(2e6)!...(1e9)! (1e6)! ,(2e 6)!. ..(1 e9)! 的階乘這樣的話,比如求( 3500000)! (3500000)! (35000 00)! 就可以看成 : 3 e6 !∗(3 e6+1 )∗(3 e6+2 )... (3e6 +5e5 )3e6! * (3e6+1)*(3e6+2) ... (3e6+5e5) 3e6!∗( 3e6+ 1)∗( 3e6+ 2).. .(3e 6+5e 5)因為( 3e 6) !(3e6)! (3e6)! 的值是已知的,故我們只需要暴力算後面的部分。 這樣每次暴力算的部分一定是小於 1e6 1e61e 6的,對於上例只需要求到5e5 5e55e 5。這樣就大大降低了複雜度,最後 15ms 15ms 15ms 就能過掉啦~ **:#include
#include
#include
#include
#include
using
namespace std;
typedef
long
long ll;
const ll m =
1e6;
const ll mod =
1e9+7;
ll fac=
;//表太長,此處省略,想參考的朋友見部落格末尾
ll get
(ll x)
return res;
}int
main()
else
} ll ans =1;
for(ll i=m ;i>=m-x+
1;i--
) ans = ans*i%mod;
for(ll i=n-m;i>=n-m-y+
1;i--
) ans = ans*i%mod;
ans = ans*
get(n-x-y)
%mod;
printf
("%i64d\n"
,ans)
;return0;
}
//表
ll fac = ;
51Nod1799 二分答案
lyk最近在研究二分答案類的問題。對於乙個有n個互不相同的數且從小到大的正整數數列a 其中最大值不超過n 若要找乙個在a中出現過的數字m,乙個正確的二分程式是這樣子的 l 1 r n mid l r 2 while l r 最終a r 一定等於m。但是這個和諧的程式被熊孩子打亂了。熊孩子在一開始就將...
51nod1799 二分答案 分塊打表
分析 要走到乙個位置的話一共要往左或者往右走o logn 次,而且每一步都必須走對。因為對於題目中給出的 無論k是什麼樣的數,二分過程的次數都是固定的。每走一步只和ami d 的大小關係有關,因此有一些位置只能放 m 或者 m的數,其他 位置可以隨便放。階乘可 以分段打表。includeusing ...
二分 假 數論 分數
nput 第一行包含兩個正整數n和p,表示選手的個數以及精度要求。接下來的n行,每行包含乙個0到100 閉區間 內的整數。output 輸出乙個實數,取p位有效數字,下取整。sample input 5 4 100 20 15 10 8 sample output 195.2 data constr...