Uva12034 (组合数取模)
Posted romalzhih
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Uva12034 (组合数取模)相关的知识,希望对你有一定的参考价值。
题意:两匹马比赛有三种比赛结果,n匹马比赛的所有可能结果总数
解法:
设答案是f[n],则假设第一名有i个人,有C(n,i)种可能,接下来还有f(n-i)种可能性,因此答案为 ΣC(n,i)f(n-i)
另外这里给出两个求组合数的模板,卢卡斯定理的p是模数,并且要求是素数,第二个是递推式,适合于n<2000的情况
1 #include<cstdio> 2 using namespace std; 3 const int maxn = 1e3; 4 const int mod = 10056; 5 typedef long long ll; 6 7 /*--------------------------卢卡斯定理取模-----------------------*/ 8 ll exp_mod(ll a, ll b, ll p) { 9 ll res = 1; 10 while (b != 0) { 11 if (b & 1) res = (res * a) % p; 12 a = (a*a) % p; 13 b >>= 1; 14 } 15 return res; 16 } 17 18 ll Comb(ll a, ll b, ll p) { 19 if (a < b) return 0; 20 if (a == b) return 1; 21 if (b > a - b) b = a - b; 22 23 ll ans = 1, ca = 1, cb = 1; 24 for (ll i = 0; i < b; ++i) { 25 ca = (ca * (a - i)) % p; 26 cb = (cb * (b - i)) % p; 27 } 28 ans = (ca*exp_mod(cb, p - 2, p)) % p; 29 return ans; 30 } 31 //Lucas定理对组合数取模 32 ll Lucas(int n, int m, int p) { 33 ll ans = 1; 34 while (n&&m&&ans) { 35 ans = (ans*Comb(n%p, m%p, p)) % p; 36 n /= p; 37 m /= p; 38 } 39 return ans; 40 } 41 42 /*----------------------组合数递推公式(适用n<2000)---------------------------*/ 43 int C[maxn+10][maxn+10]; 44 void Cal_C(int n) { 45 //传递的是一个二维的数组c 46 for (int i = 0; i <= n; i++){ 47 C[i][0] = C[i][i] = 1; 48 for (int j = 1; j < i; j++) 49 C[i][j] = (C[i - 1][j - 1]%mod + C[i - 1][j]%mod)%mod; 50 } 51 return; 52 } 53 /*--------------------------------------------------------------------------*/ 54 55 int f[maxn+11]; 56 void generate() { 57 Cal_C(maxn); 58 f[0] = 1; 59 for (int i = 1; i <= maxn; i++) { 60 f[i] = 0; 61 for (int j = 1; j <= i; j++) 62 f[i] = (f[i] + C[i][j] * f[i - j]) % mod; 63 } 64 return; 65 } 66 67 int main() { 68 int T; scanf("%d", &T); 69 int kase = 1; 70 generate(); 71 while (T--) { 72 int n; scanf("%d", &n); 73 printf("Case %d: %d ", kase++, f[n]); 74 } 75 return 0; 76 }
以上是关于Uva12034 (组合数取模)的主要内容,如果未能解决你的问题,请参考以下文章