组合数重点整理
来源:互联网 发布:fedora yum 编辑:程序博客网 时间:2024/05/18 01:12
总结下最近刷过的关于组合数的题目,以供以后复习参考。
首先要介绍的就是lucas定理,这也是组合数中重点中的重点。
同时,因为我们也经常要遇到关于取模的运算,所以关于逆元的概念也必不可少。
好了,接下来就是通过解决实际问题,来实践了。
1.hdu3037
解析:通过隔板法,求C(n+m , m )% p即可,这里我们就需要用到lucas定理了,注意,我们一般会预处理一些所需要的阶乘运算,以便后来方便使用,降低复杂度,在这道题里面,我们预先处理了0~p的阶乘。
/*ID: CaoLeiPROG: hdu_3037.cppLANG: C++*/#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <set>#include <queue>#include <map>#include <vector>using namespace std;#define N 100010#define pi acos(-1.0)#define inf 100000000typedef long long ll;typedef unsigned long long ull;ll p;ll fact[N];void init(){ fact[0]=1; for(int i=1;i<=p;i++) fact[i]=fact[i-1]*i%p;}ll pow(ll a,ll b,ll pp){ ll tmp=a,ans=1; while(b){ if(b&1){ ans=ans*tmp%pp; } b>>=1; tmp=tmp*tmp%pp; } return ans;}ll lucas(ll n,ll m,ll p){ if(m==0) return 1; else if(n%p<m%p) return 0; else return fact[n%p]*pow(fact[n%p-m%p]*fact[m%p]%p,p-2,p)%p*lucas(n/p,m/p,p)%p; //在这里面痛哇,fact[n-m]*fact[m]%p忘了模除}int main(){ freopen("in.txt","r",stdin); int t; scanf("%d",&t); ll n,m; while(t--){ scanf("%lld%lld%lld",&n,&m,&p); init(); printf("%lld\n",lucas(n+m,m,p)); } return 0;}
2.hdu3944
解析:其实将部分答案打出来仔细观察,就可以发现只需要求(C(n+1,m)+n-m)%p即可,但是注意这道题需要预处理大量的答案。
/*ID: CaoLeiPROG: hdu_3944.cppLANG: C++*/#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <set>#include <queue>#include <map>#include <cmath>#include <vector>using namespace std;#define N 10010#define pi acos(-1.0)#define inf 100000000typedef long long ll;typedef unsigned long long ull;ll p;int prime[10010];bool is[10010];int fact[N*1250];ll pow(ll a,ll b,ll pp){ ll tmp=a,ans=1; while(b){ if(b&1){ ans=ans*tmp%pp; } b>>=1; tmp=tmp*tmp%pp; } return ans;}ll getint(){ char ch=getchar(); ll ret=0; while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9'){ ret=ret*10+ch-'0';ch=getchar(); } return ret;} ll lucas(ll n,ll m,ll p){ if(m==0) return 1; else if(n%p<m%p) return 0; else return (ll)fact[n%p+prime[p]]*pow((ll)fact[n%p-m%p+prime[p]]*fact[m%p+prime[p]]%p,p-2,p)%p*lucas(n/p,m/p,p)%p; }int main(){ freopen("in.txt","r",stdin); int po=0; is[0]=is[1]=true; for(int i=2;i<=10000;i++){ if(!is[i]){ prime[i]=po*10000; fact[po*10000]=1; for(int j=po*10000+1;j<=po*10000+i;j++){ fact[j]=(ll)fact[j-1]*ll(j-po*10000)%(ll)i; } po++; for(int j=2*i;j<=10000;j+=i) is[j]=true; } } ll n,m; int cnt=1; while(~scanf("%lld",&n)){ m=getint(); p=getint(); if(m>n/2) m=n-m; printf("Case #%d: %lld\n",cnt++,(lucas(n+1,m,p)+n-m)%p); } return 0;}
3.hdu4349
解析:这时候就要借鉴《初等数论》上的结论了。
/*ID: CaoLeiPROG: hdu_4349.cppLANG: C++*/#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <set>#include <queue>#include <map>#include <cmath>#include <vector>using namespace std;#define N 500010#define pi acos(-1.0)#define inf 100000000typedef long long ll;typedef unsigned long long ull;int main(){ int n,k; while(~scanf("%d%d",&n,&k)){ while(n){ if(n%2==0&&k%2==1) break; n>>=1; k>>=1; } if(n) printf("0\n"); else printf("1\n"); } return 0;}
4.poj3146
解析:这道题我按照上一题的结论试了试,就AC了。
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <set>#include <queue>#include <map>#include <cmath>#include <vector>using namespace std;#define N 1010#define pi acos(-1.0)#define inf 100000000typedef long long ll;typedef unsigned long long ull;int main(){ int p,n,cnt=0; int ans; while(~scanf("%d%d",&p,&n)){ if(p==0&&n==0) break; ans=1; while(n){ ans*=(n%p+1); ans%=10000; n/=p; } printf("Case %d: ",++cnt); if(ans<10) printf("000%d\n",ans); else if(ans<100) printf("00%d\n",ans); else if(ans<1000) printf("0%d\n",ans); else printf("%d\n",ans); } return 0;}
5.zoj3557
解析:同样是隔板问题,但是要注意下预处理。
/*ID: CaoLeiPROG: zoj_3557.cppLANG: C++*/#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <set>#include <queue>#include <map>#include <cmath>#include <vector>using namespace std;#define N 500010#define pi acos(-1.0)#define inf 100000000typedef long long ll;typedef unsigned long long ull;ll p;ll fact[N];ll pow(ll a,ll b,ll pp){ ll tmp=a,ans=1; while(b){ if(b&1){ ans=ans*tmp%pp; } b>>=1; tmp=tmp*tmp%pp; } return ans;}ll c(ll n,ll m){ ll a=1; for(int i=n;i>n-m;i--) a=a*i%p; a=a*pow(fact[m]%p,p-2,p)%p; return a;}ll lucas(ll n,ll m,ll p){ if(m==0) return 1; else if(n%p<m%p) return 0; else return c(n%p,m%p)%p*lucas(n/p,m/p,p)%p; //在这里面痛哇,fact[n-m]*fact[m]%p忘了模除}int main(){ freopen("in.txt","r",stdin); ll n,m; while(~scanf("%lld%lld%lld",&n,&m,&p)){ fact[0]=1; for(int i=1;i<=m;i++){ fact[i]=fact[i-1]*i%p; } printf("%lld\n",lucas(n-m+1,m,p)); } return 0;}
(持续更新中)
0 0
- 组合数重点整理
- 组合数模版 整理
- 金融法重点复习(整理)
- Javaweb重点知识整理
- 【计算机网络】重点整理
- JavaScript 脚本语言 重点整理
- 计算机网络重点整理
- C++重点知识整理
- Linux重点知识整理
- 数据库重点整理
- 组合数学-离散数学重点摘记
- 组合数
- 组合数
- 组合数
- 组合数
- 组合数
- 组合数
- 组合数
- STM32+TFT彩屏实现汉字字库显示
- 【Material Design】主题与布局
- java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.AndroidCaptureC
- Linux usb_device usb_bus usb_driver的三角关系-USB Device
- 集合框架知识点总结(1)
- 组合数重点整理
- 第三方API使用方案
- 如何自定义ViewGroup
- cs193P assignmentV 问题1
- hdoj 2141 can you find it ?
- cocos2d-x改进的粒子系统和编辑器(需求分析)
- uva 120 Stacks of Flapjacks(练习deque)
- UVA - 1161 Objective: Berlin(最大流+时序模型)
- POJ1635(Subway tree systems)