一道超級數學題......

題目如有雷同,純屬巧合......

 

 

 

MTOI

【問題描述】

MT剛接觸到了冒泡排序的時候,覺得這個東西太慢了,但是加上break的效果怎麼樣呢?於是他開始考慮這樣一個問題:任意一個N的排列中,有多少種需要恰好掃K次才能使得數列從小到大排列。所謂掃就是第一重循環,當數列有序後程序會自動退出循環。

冒泡排序代碼:

Var

 a:array[0..n] of longint;

For i:=1 to n-1 do

  For j:=n downto i+1 do

If a[j]<a[j-1] then

  Swap(a[j],a[j-1]);

【輸入格式】

第一行一個數T,表示數據組數

接下來T行,每行兩個整數N,K

【輸出格式】

T個數,表示答案mod 1000000007

【樣例輸入】

3

    3 0

    3 1

    3 2

 

【樣例輸出】

    1

    3

    2

 

【數據說明】

30%T<=10N<=7

100%T ≤ 100,000

1 ≤ N ≤ 1,000,000, 0 ≤ K  N – 1

 

 

我一開始以爲是動規,結果花了20分鐘打表,30分鐘找規律,然後打了個40分的動規(當時居然不準重測,說了空間是512M結果只允許128M,我就全超了,該空間可以對40分......),後來有位神牛打了一份解題報告(沒看懂,複製了下來):

 

公式:

K!((K + 1) ^ (N - K) - K ^ (N - K))

好吧,現在讓我們來證明一下。

首先,冒泡的兩種寫法對答案是沒有影響的。

一:

Var

 a:array[0..n] of longint;

For i:=1 to n-1 do

  For j:=n downto i+1 do

If a[j]<a[j-1] then

  Swap(a[j],a[j-1]);

 

二:

Var

 a:array[0..n] of longint;

For i:=n-1 downto 1 do

  For j:=1 to i do

If a[j]>a[j+1] then

Swap(a[j],a[j+1]);

爲方便敘述,這裏根據第二種寫法討論,

首先定義函數d(x),對於1~N的一個排列,d(x)表示x個數位置)前面有多少個數字大於該數。(對應到第一種寫法就是第x個數後面有多少個數小於該數,因此兩問題是一樣的)

比如說對於3 2 4 1 5,有d(1) = 0d(2) = 1d(3) = 0d(4) = 3d(5) = 0

現在我們來證明d(x)函數的兩條性質:

(一)對於一個排列,對於所有x <= N,有d(x) = 0是這個排列是有序的充要條件。

(二)冒泡排序的每次掃描的結果是,對於非零的d(x)值,這個位置的d(x)會且只會減少1

我們得出對於1~n的一個排列,它所需要的冒泡排序的掃描次數爲

K = max (d(i), 1 <= i <= N)

而這個結論很顯然,因爲只有經過K次掃描,所有位置的d值才能都變爲0

到此,我們成功地將冒泡排序的次數問題轉化爲d(x)值滿足條件的數列的問題。原問題也就轉化成了有多少個排列使得其中最大的d(x)值恰好爲K。然而這也是複雜的,所以說我們不妨先解決有多少個排列使得其中最大的d(x)值不大於K

首先可以確定N >= K + 1,否則不可能出現某個位置前面有K個數大於它。

然後決定原數列中1的位置。顯而易見,如果最小數的位置爲x,則其d(x) = x - 1。而d(x) <= K,故x <= K + 1,也就是說1K + 1种放置方法;而放置2的時候,我們完全可以考慮一個新的排列2~N,這時2K + 1种放置方法,然後再把1插到位置1~K + 1,而不影響其它數的d值。所以說,前N - K個數的放置方法的種類有

(K + 1) ^ (N - K)

之後只需要考慮N - K + 1 ~ N的排列即可。然而,由於整個數列只有K個數字,不可能出現某個d值大於K + 1。所以說排列方法有K!種。故,所有位置d值不大於K的排列的方案數有

K!((K + 1) ^ (N - K))

但是這是不大於K的排列數量,恰好爲K的有怎麼辦呢?很簡單,只需要減去不大於K - 1的排列數量便可。所以最後的答案爲

K!((K + 1) ^ (N - K)) - (K - 1)!(K ^ (N - K + 1))

化簡之後我們就得到

K!((K + 1) ^ (N - K) - K ^ (N - K))

這就是原來的式子,它的正確性就證明完畢。

 

 

 

以上爲引用 ,然後快速冪就做出來了......

 

 

動規如下(N*K):

 

 

 

 

 

數學歸納法:

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章