求组合数
1:暴力求法,n<15
int C(int n,int m) { int mod=10007; int ans=1; for(int i=n;i>=(n-m+1);i--) ans*=i; while(m) ans/=m--; return ans%mod; }
2:打表 n<1e4
int C[1005][1005]; void init() { for(int i=0;i<=1005;i++) C[0][i]=0,C[i][0]=1; for(int i=1;i<=1005;i++) { for(int j=1;j<=1005;j++) C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod; } }
ll c[100010][5]; void init() { c[0][0]=1; for(int i=1;i<=100001;i++) { c[i][0]=1; for(int j=1;j<=4;j++) c[i][j]=(c[i-1][j]+c[i-1][j-1]); } }
3:质因数分解
大数:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN = 5005; bool isp[MAXN]; int cnt=0; int pre[MAXN],rat[MAXN]; void prime(int n) { for(int i=2;i<=n;i++) { if(!isp[i]) pre[cnt++]=i; for(int j=0;j<cnt&&pre[j]<=n/i;j++) { isp[i*pre[j]]=true; if(!(i%pre[j])) break; } } } int rate(int n,int p) { int res=0; while(n) { res+=n/p; n/=p; } return res; } vector <int> Mul(vector <int> a,int b) { vector<int>p; int t=0; for(int i=0;i<a.size();i++) { t+=a[i]*b; p.push_back(t % 10); t/=10; } while(t) { p.push_back(t%10); t/=10; } return p; } int main( ) { int a,b; scanf("%d%d",&a,&b); prime(a); for(int i=0;i<cnt;i++) { int p=pre[i]; rat[i]=rate(a,p)-rate(b,p)-rate(a-b,p); } vector<int>res; res.push_back(1); for(int i=0;i<cnt;i++) { for(int j=0;j<rat[i];j++) res=Mul(res,pre[i]); } for(int i=res.size()-1;~i;i--) printf("%d", res[i]); return 0; }
非大数:
#include <cstdio> const int maxn=1000000; #include <vector> using namespace std; typedef long long ll; bool arr[maxn+1]={false}; vector<int> produce_prim_number() { vector<int> prim; prim.push_back(2); int i,j; for(i=3;i*i<=maxn;i+=2) { if(!arr[i]) { prim.push_back(i); for(j=i*i;j<=maxn;j+=i) arr[j]=true; } } while(i<maxn) { if(!arr[i]) prim.push_back(i); i+=2; } return prim; } int cal(int x,int p) { int ans=0; ll rec=p; while(x>=rec) { ans+=x/rec; rec*=p; } return ans; } int pow(ll n,int k,int M) { ll ans=1; while(k) { if(k&1) ans=(ans*n)%M; n=(n*n)%M; k>>=1; } return ans; } int combination(int n,int m) { const int M=10007; vector<int> prim=produce_prim_number(); ll ans=1; int num; for(int i=0;i<prim.size()&&prim[i]<=n;i++) { num=cal(n,prim[i])-cal(m,prim[i])-cal(n-m,prim[i]); ans=(ans*pow(prim[i],num,M))%M; } return ans; } int main() { int m,n; while(~scanf("%d%d",&m,&n),m&&n) { printf("%d\n",combination(m,n)); } return 0; }
4:Lucas定 (long long) n和m较大,但是p为素数的时候,求 c(n,m) mod p
#include <iostream> using namespace std; typedef long long ll; #define mod 1000000007 ll ksm(ll a,ll b) { ll ans=1; while(b) { if(b&1) ans=ans*a%mod; a=a*a%mod; b>>=1; } return ans; } ll zuheshu(ll a,ll b) { if(a<b) return 0; if(a==b) return 1; ll u=1,d=1; for(ll i=1;i<=a;i++) u=u*i%mod; for(ll i=1;i<=b;i++) d=d*i%mod; for(ll i=1;i<=a-b;i++) d=d*i%mod; return u*ksm(d,(mod-2))%mod; } int main( ) { ll n,m;; while(cin>>n>>m) { cout<<zuheshu(n,m)<<endl; } return 0; }
5: long long
#include <iostream> using namespace std; typedef long long ll; ll C(ll x, ll y) { ll a=x+y; ll b=min(x,y); double t=1.0; while(b>0) t*=(double)(a--)/(double)(b--); t+=0.5; return (ll)t; } int main( ) { ll n,m; while(cin>>n>>m) { if(n==0&&m==0) break; cout<<C(n,m)<<endl; } return 0; }