洛谷 p1641 [scoi2010]生成字串
題目描述
lxhgww最近接到了乙個生成字串的任務,任務需要他把n個1和m個0組成字串,但是任務還要求在組成的字串中,在任意的前k個字元中,1的個數不能少於0的個數。現在lxhgww想要知道滿足要求的字串共有多少個,聰明的程式設計師們,你們能幫助他嗎?
輸入格式:
輸入資料是一行,包括2個數字n和m
輸出格式:
輸出資料是一行,包括1個數字,表示滿足要求的字串數目,這個數可能會很大,只需輸出這個數除以20100403的餘數。
輸入輸出樣例輸入
輸出2 2
29 7
3432
說明題目標籤:組合數學 逆元
聽說這好像時一道高考題orz
用n代表1的個數,m代表0的個數,設 x=n+m,y=n-m,建立直角座標系,生成字串就可以用從(0,0)到(n+m,n-m)的上公升n次下降m次的折線表示,所有的情況個數為c(n+m,m)。
要滿足任意的前k個字元中,1的個數大於等於0的個數,也就是影象要始終在x軸的上方(n-m>=0)
如果影象到了x軸下方則存在k=n+m,n-m<0,1的個數小於0的個數
直接求影象在x軸上方的所有情況個數有點困難,根據對稱性可以轉化一下
影象有在x軸下方的情況可以看作折線到達y=-1
將影象到達y=-1之前的影象關於直線y=-1對稱翻摺可以得到
從(0,0)到達y=-1,下降的次數比上公升的次數多一次,翻摺後,可以看成從(0,-2)到y=-1,上公升的次數比下降的次數多一次,這樣,所有存在n-m小於0的情況數等於從(0,-2)上公升n+1次下降m-1次的折線圖像的所有情況個數:c(n+m,m-1)。
所以答案就為c(n+m,m)-c(n+m,m-1)
然後就是處理組合數的問題了,這個資料範圍,用楊輝三角打表不現實,只能逆元打表了,之後用公式求組合數
在模質數m下,求1~n的逆元(n板子:
const int maxn = 1e6+5;
int inv[maxn];
void inverse(int n,int m)
}
推導過程:
由 (m/i) * i + m%i = 0 (mod m)
=> -(m/i) * i = m%i (mod m) 兩邊同時除以 (m%i )*i
=> -(m/i) * (1/(m%i)) = 1/(i) (mod m)
即:-(m/i) * inv[m%i] = inv[i] (mod m)
所以:inv[i]=(m-m/i) * inv[m%i]%m
**:
#include
#define ll long long
using
namespace std;
const ll m =
20100403
;const
int n =
1e6+10;
int inv[n]
,fac[n]
,n,m;
void
init
(int n)
inv[1]
=1;for
(int i=
2;i<=n;i++
)for
(int i=
2;i<=n;i++)}
intcomb
(int a,
int b)
intmain()
int an=
(comb
(m+n,m)
-comb
(m+n,m-1)
)%m;
cout<
return0;
}
洛谷 P1641 SCOI2010 生成字串
題目描述 lxhgww最近接到了乙個生成字串的任務,任務需要他把n個1和m個0組成字串,但是任務還要求在組成的字串中,在任意的前k個字元中,1的個數不能少於0的個數。現在lxhgww想要知道滿足要求的字串共有多少個,聰明的程式設計師們,你們能幫助他嗎?輸入格式 輸入資料是一行,包括2個數字n和m 輸...
洛谷 P1641 SCOI2010 生成字串
洛谷 這題一看就是卡塔蘭數。因為 cnt 1 leq cnt 0 很顯然的卡塔蘭嘛!平時我們推導卡塔蘭是用乙個邊長為n的正方形推的,相當於從 0,0 點走到 n,n 點,向上走的步數不能超過向右走,求出的方案數就是卡塔蘭數。即總方案 不合法方案 frac 這題只是改成了從 0,0 走到 n,m 點,...
P1641 SCOI2010 生成字串
lxhgww最近接到了乙個生成字串的任務,任務需要他把n個1和m個0組成字串,但是任務還要求在組成的字串中,在任意的前k個字元中,1的個數不能少於0的個數。現在lxhgww想要知道滿足要求的字串共有多少個,聰明的程式設計師們,你們能幫助他嗎?輸入資料是一行,包括2個數字n和m 輸出資料是一行,包括1...