hdu 3037 Saving Beans(组合数取模)
来源:互联网 发布:邢台程序员招聘 编辑:程序博客网 时间:2024/05/05 14:41
Saving Beans
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3697 Accepted Submission(s): 1424
Now they turn to you for help, you should give them the answer. The result may be extremely huge; you should output the result modulo p, because squirrels can’t recognize large numbers.
Then followed T lines, each line contains three integers n, m, p, means that squirrels will save no more than m same beans in n different trees, 1 <= n, m <= 1000000000, 1 < p < 100000 and p is guaranteed to be a prime.
21 2 52 1 5
33HintHintFor sample 1, squirrels will put no more than 2 beans in one tree. Since trees are different, we can label them as 1, 2 … and so on. The 3 ways are: put no beans, put 1 bean in tree 1 and put 2 beans in tree 1. For sample 2, the 3 ways are: put no beans, put 1 bean in tree 1 and put 1 bean in tree 2.
题解:组合数取模(lucas定理)
题目大意:从n棵不同的树上取不超过M颗豆子(豆子无差异),有多少种取法。
题目可以转换成 x1+x2+……+xn=m 有多少组解,m在题中可以取0~m。
对于 x1+x2+……+xn=m,需要利用到插板法。
插板法:插板法就是在n个元素间的(n-1)个空中插入 若干个(b)个板,可以把n个元素分成(b+1)组的方法。
应用插板法必须满足三个条件:
(1) 这n个元素必须互不相异
(2) 所分成的每一组至少分得一个元素
(3) 分成的组别彼此相异
那么这相当于是m 个元素,插入n个板子,但是所分成的每组元素可以剩余,条件(2)不满足,此时如果在3个箱子种各预先插入1个元素,则问题就等价于把n+m个元素插入n个板子,此时的答案就是C(n+m-1,n-1) =C(n+m-1,m) (C(N,M)=C(N,N-M)) 。
则题目解的个数可以转换成求 sum=C(n+m-1,0)+C(n+m-1,1)+C(n+m-1,2)……+C(n+m-1,m)利用公式C(n,r)=C(n-1,r)+C(n-1,r-1) == > sum=C(n+m,m)。
sum=C(n+m-1,0)(m=0)+C(n+m-1,1)(m=1)+C(n+m-1,2)(m=2)……+C(n+m-1,m)(m=m)
=C(n-1,0)+C(n,1)+C(n+1,2)....+C(n-m-1,m)
因为C(n-1,0)=C(n,0)=1
所以式子可以利用C(n,r)=C(n-1,r)+C(n-1,r-1) ,进行化简最终得到C(n+m,m)
现在就是要求C(n+m,m)%p。
lucas定理:
A、B是非负整数,p是质数。AB写成p进制:A=a[n]a[n-1]...a[0],B=b[n]b[n-1]...b[0]。
则组合数C(A,B)与C(a[n],b[n])*C(a[n-1],b[n-1])*...*C(a[0],b[0]) modp同余
即:Lucas(n,m,p)=c(n%p,m%p)*Lucas(n/p,m/p,p)
但是lucas定理只有在A,B<=10^18,P为质数,p<=10^5时才可以使用(如果p<=10^9,但是n,m较小的话,貌似也可以用lucas定理,但是没法预处理阶乘,只能单独计算组合数,总之具体情况具体分析)
这道题的话可以先预处理出阶乘,根据公式c(n,m)=n!/(m!(n-m)!),因为是模意义下所以可以转化为n!*inv(m!(n-m)!) mod p,因为p是质数,根据费马小定理,可得 inv(m!(n-m)!)=(m!(n-m)!)^p-2,可用快速幂求解。
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#define ll long longusing namespace std;ll k[500003],n,m,p;int t;void calc(ll p){ k[0]=1; for (ll i=1;i<=p;i++) k[i]=(ll)k[i-1]*i%p;}ll quick(ll num,ll x){ll ans=1; ll base=(ll)num%p; while(x){if (x&1) ans=ans*base%p;x>>=1;base=base*base%p;}return ans%p;}ll c(ll x,ll y){if (y>x) return 0;return (ll)k[x]*quick(k[y]*k[x-y],p-2)%p;}ll lucas(ll n,ll m,ll p){if (m==0) return 1;return (ll)c(n%p,m%p)*lucas(n/p,m/p,p)%p;}int main(){freopen("a.in","r",stdin);freopen("my.out","w",stdout);scanf("%d",&t);for (int i=1;i<=t;i++) { scanf("%I64d%I64d%I64d",&n,&m,&p); calc(p); printf("%I64d\n",lucas(n+m,m,p)%p); }}
- hdu 3037 Saving Beans(组合数取模)
- 【HDU 3037】Saving Beans(组合数取模)
- [ACM] hdu 3037 Saving Beans (Lucas定理,组合数取模)
- hdu 3037 Saving Beans (大组合数取模--Lucas定理)
- hdu-3037-Saving Beans(Lucas定理+大组合数取模)
- HDU - 3037 Saving Beans (数论,组合数取模,lucas定理)
- hdu 3037 Saving Beans 【大组合数取模-Lucas定理+逆元取模】
- 大组合数取模 hdu 3037 Saving Beans lucas定理
- hdu 3037 Saving Beans 组合数取模模板题。。
- HDU 3037 Saving Beans 组合数取模 Lucas定理
- hdu 3037 Saving Beans(组合数学)
- hdu 3037 Saving Beans
- 【hdu 3037】Saving Beans
- HDU 3037 Saving Beans
- HDU 3037 Saving Beans 大组合数 lucas定理
- hdu 3037 Saving Beans(组合数学+lucas定理)
- HDU 3037 Saving Beans(组合数学+Lucas定理)
- HDU 3037 Saving Beans (Lucas定理)
- saltstack应用之批量部署mysql
- 判断出栈顺序是否正确
- 模拟实现strstr函数
- Tomcat在linux环境下重启,无法访问项目的解决办法
- docker的学习之原理篇
- hdu 3037 Saving Beans(组合数取模)
- isa 指针
- 函数调用堆栈
- Fresco的使用
- R笔记
- Manacher算法
- Spark 基础 —— RDD(二)
- Bellman-Ford算法
- hive启动出现权限错误 /tmp/hive on HDFS should be writable.