1. 程式人生 > >BZOJ#2142. 禮物

BZOJ#2142. 禮物

IE sigma event 不同的 lld exgcd getchar() 個數 +=


題目:

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; }
View Code


BZOJ#2142. 禮物