ZOJ 3557 & BZOJ 2982 combination[Lucas定理]
Given a set S = {1, 2, ..., n}, number m and p, your job is to count how many set T satisfies the following condition:
- T is a subset of S
- |T| = m
- T does not contain continuous numbers, that is to say x and x+1 can not both in T
Input
There are multiple cases, each contains 3 integers n ( 1 <= n <= 109 ), m ( 0 <= m <= 104, m <= n ) and p ( p is prime, 1 <= p <= 109 ) in one line seperated by a single space, proceed to the end of file.
Output
Output the total number mod p.
Lucas定理p为质数情况裸题
因为是选的元素不能连续,我们先把选的元素拿出来,剩下的元素有n-m+1个空,选m个插进去行了
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; typedef long long ll; ll n,m,P; ll Pow(ll a,ll b){ ll ans=1; for(;b;b>>=1,a=a*a%P) if(b&1) ans=ans*a%P; return ans; } ll Inv(ll a){return Pow(a,P-2);} ll C(ll n,ll m){ if(n<m) return 0; ll x=1,y=1; for(ll i=n-m+1;i<=n;i++) x=x*i%P; for(ll i=1;i<=m;i++) y=y*i%P; return x*Inv(y)%P; } ll Lucas(ll n,ll m){ if(n<m) return 0; ll re=1; for(;m;n/=P,m/=P) re=re*C(n%P,m%P)%P; return re; } int main(){ //freopen("in","r",stdin); while(scanf("%lld%lld%lld",&n,&m,&P)!=EOF) printf("%lld\n",Lucas(n-m+1,m)); }
BZOJ 2982: combination
模数10007很小,可以直接线性预处理阶乘和逆元,48ms-->4ms
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; typedef long long ll; const int N=10007; inline ll read(){ char c=getchar();ll x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } ll n,m,P=10007; ll inv[N],fac[N],facInv[N]; void getInv(int n){ inv[1]=fac[0]=facInv[0]=1; for(int i=1;i<=n;i++){ if(i!=1) inv[i]=-P/i*inv[P%i]%P; inv[i]+=inv[i]<0?P:0; fac[i]=fac[i-1]*i%P; facInv[i]=facInv[i-1]*inv[i]%P; } } ll C(ll n,ll m){ if(n<m) return 0; return fac[n]*facInv[m]%P*facInv[n-m]%P; } ll Lucas(ll n,ll m){ if(n<m) return 0; ll re=1; for(;m;n/=P,m/=P) re=re*C(n%P,m%P)%P; return re; } int main(){ freopen("in","r",stdin); getInv(N-1); int T=read(); while(T--){ n=read();m=read(); printf("%lld\n",Lucas(n,m)); } }
Copyright:http://www.cnblogs.com/candy99/