[SCOI2010]生成字串
阿新 • • 發佈:2018-12-08
題目描述
lxhgww最近接到了一個生成字串的任務,任務需要他把n個1和m個0組成字串,但是任務還要求在組成的字串中,在任意的前k個字元中,1的個數不能少於0的個數。現在lxhgww想要知道滿足要求的字串共有多少個,聰明的程式設計師們,你們能幫助他嗎?
輸入輸出格式
輸入格式:
輸入資料是一行,包括2個數字n和m
輸出格式:
輸出資料是一行,包括1個數字,表示滿足要求的字串數目,這個數可能會很大,只需輸出這個數除以20100403的餘數
輸入輸出樣例
輸入樣例#1:
2 2
輸出樣例#1:
2
說明
limitation
每點2秒
對於30%的資料,保證1<=m<=n<=1000
對於100%的資料,保證1<=m<=n<=1000000
題解
一眼組合數
然後想到像catalan數那樣把\(0/1\)轉化到座標系中
然後就越走越偏==
正解是類似Catalan數的推導公式的東西
選1就是\((x,y) -> (x+1,y+1)\)
選0就是\((x,y) -> (x+1,y-1)\)
所以構成\(0/1\)字串的方案數就是\(C(n+m,m)\)
然後有一個條件就是任何時候1的數量都不小於0的數量
所以答案就是從\((0,0)\)出發不碰到\(y=-1\)的路徑
考慮怎麼去掉碰到\(y=-1\)的路徑
我們可以把從\((0,0)\)碰到\(y=-1\)
就是從\((0,-2)\)走\(n+m\)步走到\((n,n-m)\)的方案數
所以答案就是走\(n+m+1\)步1,走\(m-1\)步0
#include<cstdio> #include<iostream> # define int long long const int M = 2000005 ; const int mod = 20100403 ; using namespace std ; int n , m ; int Fac[M] , Ans ; inline int Fpw(int Base , int k) { int temp = 1 ; while(k) { if(k & 1) temp = (temp * Base) % mod ; Base = (Base * Base) % mod ; k >>= 1 ; } return temp ; } inline int C(int n , int m) { return (Fac[n] * Fpw((Fac[m] * Fac[n - m]) % mod , mod - 2)) % mod ; } # undef int int main() { # define int long long cin >> n >> m ; Fac[0] = 1 ; for(int i = 1 ; i <= n + m ; i ++) Fac[i] = (Fac[i - 1] * i) % mod ; cout << (C(n + m , m) - C(n + m , m - 1) + mod) % mod << endl ; return 0 ; }