CSU 1320:Scoop water(卡特兰数)
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1320
题意:……是舀的时候里面必须要有1L,而不是舀完必须要有1L。
思路:才知道是卡特兰数。
这个感觉写的很好 http://www.cnblogs.com/wuyuegb2312/p/3016878.html
卡特兰数可以解决:求括号匹配,出栈入栈等组合个数的问题。
卡特兰数公式:
first O(n): h(n) = h(n-1) * (4*n-2) / (n+1)
second O(n^2): h(n) = h(0)*h(n-1) + h(1)*h(n-2) …… + h(n-1)*h(0)
third 直接算的公式:h(2n) = C(n, 2n) / (n+1)
第一种计算要用到逆元
逆元: 费马小定理
a^(m-1) ≡ 1(mod m)
a * a^(m-2) ≡ 1(mod m)
a^(m-2) ≡ (1/a)(mod m)
1 #include <cstdio> 2 using namespace std; 3 typedef long long LL; 4 #define N 10010 5 #define MOD 1000000007 6 LL f[N]; 7 /* 8 卡特兰数公式: 9 first O(n): h(n) = h(n-1) * (4*n-2) / (n+1) 10 second O(n^2): h(n) = h(0)*h(n-1) + h(1)*h(n-2) …… + h(n-1)*h(0) 11 逆元: 费马小定理 12 a^(m-1) ≡ 1(mod m) 13 a * a^(m-2) ≡ 1(mod m) 14 a^(m-2) ≡ (1/a)(mod m) 15 */ 16 LL q_pow(LL a, LL b) { 17 LL ans = 1; 18 a %= MOD; b %= MOD; 19 while(b) { 20 if(b & 1) ans = (ans * a) % MOD; 21 b >>= 1; 22 a = (a * a) % MOD; 23 } 24 return ans; 25 } 26 // 快速乘(貌似鸡肋) 27 LL q_mul(LL a, LL b) { 28 LL ans = 0; 29 a %= MOD; 30 while(b) { 31 if(b & 1) {ans = (ans + a) % MOD; b--;} 32 b >>= 1; 33 a = (a + a) % MOD; 34 } 35 return ans % MOD; 36 } 37 38 void dabiao() { 39 f[0] = f[1] = 1LL; 40 for(int i = 2; i <= 10000; i++) // first 41 f[i] = f[i-1] * (4 * i - 2) % MOD * q_pow(i + 1, MOD - 2) % MOD; 42 // for(int i = 2; i <= 10000; i++) second 43 // for(int j = 0; j < i; j++) 44 // f[i] = (f[i] + f[i-j-1] * f[j] % MOD) % MOD; 45 } 46 47 int main() { 48 int n; dabiao(); 49 while(~scanf("%d", &n)) printf("%lld\n", f[n] % MOD); 50 return 0; 51 }