HDU 3944
来源:互联网 发布:线切割锥度编程 编辑:程序博客网 时间:2024/05/01 20:01
原来剑哥讲组合数取模的时候说过Lucas定理,但是不是很明白。总之C(n,k)%p = C(n/p,k/p)*C(n%p,k%p)%p。这里要注意如果k>n, C(n,k)=0。C(n,k)%p可以通过求逆元的方法计算。不过C(n,k)%p = n!/(k!*(n-k)!)%p = n!*((k!*(n-k)!)^(p-2))%p是更好的方法,编码简单一点,时间效率高一点。
还要注意一点,这题比较恶心,每次都初始化阶乘数组肯定会超时。考虑到10000以内只有1229个素数,所以可以先打表。
#include <stdio.h>#include <stdlib.h>#include <math.h>#include <string.h>#include <memory.h>#include <string>#include <vector>#include <map>#include <set>#include <queue>#include <algorithm>#include <iostream>#include <sstream>using namespace std;// Lucas定理求解C(n,k)%p, p是素数// C(n,k)%p = C(n%p,k%p)*C(n/p,k/p)%p// C(n,k)%p = n!/(k!*(n-k)!)%p = n!*((k!*(n-k)!)^(p-2))%p// pow_mod(a,b,p)求a^b%p的值, 快速幂取模算法// com_mod(n,k,p)求C(n,k)%p的值// lucas(n,k,p)使用lucas定理求C(n,k)%p的值int pow_mod(int a, int b, int p) { int r = 1, t = a; while (b) { if (b & 1) r = r * t % p; t = t * t % p; b >>= 1; } return r;}int com_mod(int n, int k, int p, int *fac) { int a, b; if (k > n) return 0; a = fac[n]; b = fac[n-k] * fac[k] % p; return a * pow_mod(b, p-2, p) % p;}int lucas(int n, int k, int p, int *fac) { int r = 1, a, b; while (n && k && r) { a = n % p; b = k % p; n /= p; k /= p; r = r * com_mod(a, b, p, fac) % p; } return r;}int pri[1250], cnt;int fac[1250][10000];bool not_prime[10005];void init() { int i, j, p; cnt = 0; for (i = 2; i < 10000; i++) { if (not_prime[i]) continue; pri[cnt++] = i; for (j = i + i; j < 10000; j += i) not_prime[j] = 1; } for (i = 0; i < cnt; i++) { fac[i][0] = 1; p = pri[i]; for (j = 1; j < p; j++) fac[i][j] = j * fac[i][j-1] % p; }}int *find(int p) { int l = 0, r = cnt - 1; while (l <= r) { int m = (l + r) / 2; if (pri[m] == p) return fac[m]; else if (pri[m] < p) l = m + 1; else r = m - 1; } return fac[0];}int main() { int n, k, p, t = 1; init(); while (scanf("%d %d %d", &n, &k, &p) != EOF) { if (k > n - k) k = n - k; printf("Case #%d: ", t++); printf("%d\n", (lucas(n+1, k, p, find(p)) + n - k) % p); } return 0;}
- HDU 3944
- hdu 3944
- hdu 3944 组合数学
- HDU 3944解题报告
- hdu 3944 lucas
- HDU 3944 DP?
- hdu 3944 DP?
- hdu
- hdu
- HDU
- hdu ()
- hdu
- hdu
- HDU
- HDU
- hdu
- hdu
- HDU
- Linux 下监测指定路径下指定时间间隔内是否有指定的文件的生成
- Singleton学习笔记
- 第一篇blog
- 9-6课堂笔记
- 学习《Java核心技术卷1:基础知识》中对象与类一章中遇到的问题
- HDU 3944
- MFC Windows程序设计(第二版)第一章笔记
- Android定位功能(二)
- NYoj 103 大数相加
- Gamebryo3.0SDK翻译-Lightspeed介绍
- Linux目录解释(蛮全)
- 利用ffmpeg框架扩展android平台解码器
- Gamebryo3.0SDK翻译-NiMesh
- which is 什么时候可以省略