【组合数】ZOJ3557 HDU3944
来源:互联网 发布:顶级域名证书合法吗 编辑:程序博客网 时间:2024/06/05 09:04
大佬博客:
http://blog.csdn.net/acdreamers/article/details/8037918
/*ZOJ 3557题意:从n个数中取m个数并且这m个数字之间不能相邻思路:n-m个数不取,留下n-m+1个空将这m个数插入n-m+1个空中所以C(n-m+1,m)*/#include <bits/stdc++.h>using namespace std;typedef long long LL;LL quickpow(LL x,LL n,LL p){ LL ans=1; while(n) { if(n&1) ans=ans*x%p; x=x*x%p; n>>=1; } return ans;}LL C(LL n,LL m,LL p){ LL up=1,down=1; for(int i=1;i<=m;i++) { up=up*(n-i+1)%p; down=down*i%p; } return up*quickpow(down,p-2,p)%p;}LL Lucas(LL n,LL m,LL p){ if(m==0) return 1; return C(n%p,m%p,p)*Lucas(n/p,m/p,p)%p;}int main(){ LL n,m,p; while(~scanf("%lld%lld%lld",&n,&m,&p)) { printf("%lld\n",Lucas(n-m+1,m,p)); } return 0;}
/*HDU 3944题意:给出一个杨辉三角,给出一个坐标(n,m)求(n,m)到(1,1)路径上数字的最小和思路:从(n,m)点一直向左上方走,走到边缘就一直往上走根据对称性n/2右边跟左边是一样的往上找的推的公式:主要是C(n-k,0)=C(n-k+1,0)将第一行的第一个式子替换了然后根据C(n,m)=C(n-1,m),C(n-1,m-1)不断合并c(n-k,0)+c(n-k+1,1)+c(n-k+2,2)+...+c(n-k+i,i)+...+c(n,k)+n-k=c(n-k+1,0)+c(n-k+1,1)+c(n-k+2,2)+...+c(n-k+i,i)+...+c(n,k)+n-k=c(n-k+2,1)+c(n-k+2,2)+...+c(n-k+i,i)+...+c(n,k)+n-k=c(n-k+3,2)+...+c(n-k+i,i)+...+c(n,k)+n-k=c(n-k+i,i-1)+...+c(n-k+i,i)+c(n,k)+n-k=c(n,k-1)+c(n,k)+n-k=c(n+1,k)+n-k预处理出对所有p的阶乘和逆元*/#include <bits/stdc++.h>using namespace std;typedef long long LL;const int MAXN=1e4;LL fac[MAXN+1][MAXN+1],inv[MAXN+1][MAXN+1];int prime[MAXN+1],rk[MAXN+1];void getPrime()//求素数{ memset(prime,0,sizeof(prime)); for(int i=2; i<=MAXN; i++) { if(!prime[i]) { prime[++prime[0]]=i; rk[i]=prime[0]; } for(int j=1; j<=prime[0]&&prime[j]<=MAXN/i; j++) { prime[prime[j]*i]=1; if(i%prime[j]==0) break; } }}LL quickpow(LL x,LL n,LL p)//快速幂{ LL ans=1; x%=p; while(n) { if(n&1) ans=ans*x%p; x=x*x%p; n>>=1; } return ans;}void Init()//预处理{ for(int i=1; i<=prime[0]; i++) { fac[i][0]=inv[i][0]=1; for(int j=1; j<prime[i]; j++) { fac[i][j]=(fac[i][j-1]*j)%prime[i]; inv[i][j]=quickpow(fac[i][j],prime[i]-2,prime[i]); } }}LL C(LL n,LL m,LL p)//计算组合数{ if(m>n) return 0; else if(m==n) return 1; int index=rk[p]; return fac[index][n]*(inv[index][m]*inv[index][n-m]%p)%p;}LL Lucas(LL n,LL m,LL p){ if(m==0) return 1; return C(n%p,m%p,p)*Lucas(n/p,m/p,p)%p;}int main(){ int cas=0; LL n,k,p; getPrime(); Init(); while(~scanf("%lld%lld%lld",&n,&k,&p)) { if(k>n/2) k=n-k; printf("Case #%d: %lld\n",++cas,(Lucas(n+1,k,p)+n-k)%p); } return 0;}
0 0
- 【组合数】ZOJ3557 HDU3944
- zoj3557 大组合数取模
- HDU3944 DP?(大组合数取模:lucas定理)
- [HDU3944]DP? (组合数学Lucas定理)
- [ZOJ3557]How Many Sets II(组合数学Lucas定理)
- [ZOJ3557]How Many Sets II(组合数学Lucas定理)
- B(ZOJ3557)
- 组合数
- 组合数
- 组合数
- 组合数
- 组合数
- 组合数
- 组合数
- 组合数
- 组合数
- 组合数
- 组合数
- Android6.0运行时权限以及RxPermissions的使用
- Ztree 权限分配方面的应用
- 考研英语
- 小知识
- 前端控件之Jquery datetimepicker的使用总结
- 【组合数】ZOJ3557 HDU3944
- 戴尔笔记本双显卡配置nvidia367+cuda8.0+caffe(通用版)
- 首款兼容DWM1000的远距离UWB测距模块——MAX1000
- Linux内核源码-boot下的汇编代码分析(Linux0.11)
- usecols选取指定列rename修改列名round指定有效位数
- floodlight 控制器的 ACL REST API学习笔记
- hrbust mengxiang000000 题册
- linux下安装nginx
- SQL查询语句例题