題目鏈結
很好的題目,很早就關注了此題,但一直沒看懂題解,今天在紙上模擬了很久終於了有了新的感悟
對於這種 求期望
∗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...