BZOJ#2142. 礼物
题目:
Description
一年一度的圣诞节快要来到了。每年的圣诞节小E都会收到许多礼物,当然他也会送出许多礼物。不同的人物在小E心目中的重要性不同,在小E心中分量越重的 人,收到的礼物会越多。小E从商店中购买了n件礼物,打算送给m个人,其中送给第i个人礼物数量为wi。请你帮忙计算出送礼物的方案数(两个方案被认为是 不同的,当且仅当存在某个人在这两种方案中收到的礼物不同)。由于方案数可能会很大,你只需要输出模P后的结果。
分析:
裸的Lucas
ans=∏(C(n,w) (n=n-Σwi)
式子的意思就是每次进来一个人,答案就要乘上C(n,w),n是现在还剩下的礼物个数
因为前面的人已经选走了Σwi个礼物,只剩下n-Σwi个礼物可以选
#include<bits/stdc++.h> using namespace std; long long read() { long long x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();} return x*f; } long long mod,n,m,w; long long qpow(long long a,long long b,long long p) { long long ans=1LL; while(a>0) { if(a&1) ans=(ans*b)%p; b=(b*b)%p; a>>=1; } return ans; } void exgcd(long long a,long long b,long long &x,long long &y) { if(b==0) {x=1;y=0;return ;} exgcd(b,a%b,x,y); long long temp=x; x=y; y=temp-a/b*y; } long long inv(long long a,long long p) { long long x,y; exgcd(a,p,x,y); x=(x%p+p)%p; if(!x) x=p; return x; } long long Mul(long long n,long long pi,long long pk) { if(!n) return 1LL; long long ans=1LL; if(n/pk) { for(long long i=2;i<=pk;i++) if(i%pi) ans=(ans*i)%pk; ans=qpow(n/pk,ans,pk); } for(long long i=2;i<=n%pk;i++) if(i%pi) ans=(ans*i)%pk; return (ans*Mul(n/pi,pi,pk))%pk; } long long C(long long n,long long m,long long pi,long long pk) { if(n<m) return 0; long long a=Mul(n,pi,pk),b=Mul(m,pi,pk),c=Mul(n-m,pi,pk); long long k=0; for(long long i=n;i;i/=pi) k+=i/pi; for(long long i=m;i;i/=pi) k-=i/pi; for(long long i=n-m;i;i/=pi) k-=i/pi; long long ans=((a*inv(b,pk)%pk*inv(c,pk)%pk)%pk*qpow(k,pi,pk))%pk; return ans*(mod/pk)%mod*inv(mod/pk,pk)%mod; } long long Lucas(long long n,long long m) { long long ans=0; long long x=mod; for(long long i=2;i<=x;i++) { long long pk=1; if(x%i==0) { while(x%i==0) pk*=i,x/=i; ans=(ans+C(n,m,i,pk))%mod; } } return ans; } int main() { freopen("a.in","r",stdin); mod=read();n=read();m=read(); long long ans=1; for(int i=1;i<=m;i++) { w=read(); if(n<w) {printf("Impossible\n");return 0;} ans=(ans*Lucas(n,w))%mod; n-=w; } printf("%lld\n",ans); return 0; }