hdu 3037 Saving Beans(lucas定理模板)
2015-09-16 15:19
501 查看
题意:
求在n棵树上摘不超过m颗豆子的方案,结果对p取模。解析:
题目可以转换成 x1+x2+……+xn=mx_1+x_2+……+x_n=m 有多少组解,m在题中可以取0~m。利用插板法可以得出 x1+x2+……+xn=mx_1+x_2+……+x_n=m
解的个数为Cn−1n+m−1=Cmn+m−1C_{n+m-1}^{n-1}=C_{n+m-1}^m;
则题目解的个数可以转换成求 sum=C0n+m−1+C1n+m−1+C2n+m−1……+Cmn+m−1sum = C_{n+m-1}^0+C_{n+m-1}^1 + C_{n+m-1}^2……+C_{n+m-1}^m
利用公式Crn=Crn−1+Cr−1n−1==>sum=Cmn+mC_n^r = C_{n-1}^r+C_{n-1}^{r-1} == > sum=C_{n+m}^m。
那么答案,就是要求Cmn+m%pC_{n+m}^m\%p。
因为n,m很大,这里可以直接套用Lucas定理的模板即可。
关于Lucas定理
Lucas(n,m,p)=C(n%p,m%p,p)∗Lucas(n/p,m/p,p)Lucas(n,m,p) = C(n\%p,m\%p,p) * Lucas(n/p, m/p, p)//这里可以采用对n分段递归求解
Lucas(x,0,p)=1Lucas(x, 0, p)=1
将n,mn,m分解变小之后问题又转换成了求(a/b)%p(a/b)\%p。
(a/b)%p(a/b)\%p可以转换成a∗Inv(b,p)a*Inv(b,p)
Inv(b,p)Inv(b, p)为b对p的逆元。
mymy codecode
[code]#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N = 100005; ll fac ; ll modpow(ll a, ll b, ll MOD) { ll ret = 1; while(b) { if(b&1) ret = (ret*a)%MOD; a = (a*a)%MOD; b>>=1; } return ret; } ll getFactor(ll p) { fac[0] = 1; for(int i = 1; i <= p; i++) fac[i] = (fac[i-1]*i) % p; } ll Lucas(ll n, ll m, ll p) { ll ret=1; while(n && m) { ll a = n%p, b = m%p; if(a<b) return 0; ret = (ret * fac[a] * modpow(fac[b]*fac[a-b]%p, p-2, p)) % p; n/=p; m/=p; } return ret; } int main() { int T; scanf("%d", &T); while(T--) { ll n, m, p; scanf("%I64d%I64d%I64d", &n, &m, &p); getFactor(p); printf("%I64d\n",Lucas(n+m,m,p)); } return 0; }
相关文章推荐
- 将中缀表达式转化为逆波兰式(c++实现)
- 总结八大排序算法的基本思想与代码实现
- linux进程状态浅析
- Sublime插件库新成员基于APICloud快速开发跨平台App
- iOS实现UIImageView透明区域点击事件穿透
- 使用CXF框架学习搭建WebService(二)
- 修改bug小经验积累总结
- iOS 归档 保存对象到本地
- 使用FD_CLOEXEC实现close-on-exec,关闭子进程无用文件描述符 http://blog.csdn.net/chrisniu1984/article/details/7050663
- Nginx Location配置总结
- 一般线性规划求最小值+c语言
- 【BZOJ1044】【HAOI2008】木棍分割 动态规划
- Android Studio 快捷键
- 约束下的最优求解:拉格朗日乘数法和KKT条件
- 《程序员面试金典》空格替换
- C# - object有哪些基本方法类有
- primefaces dataExporter export invisible dataTable rows
- AppStore预览视频AppPreviews制作总结
- 新到惠普
- ubuntu双系统装机集中贴