zoukankan      html  css  js  c++  java
  • BZOJ2142: 礼物

    BZOJ2142: 礼物

    Description

    一年一度的圣诞节快要来到了。每年的圣诞节小E都会收到许多礼物,当然他也会送出许多礼物。不同的人物在小E
    心目中的重要性不同,在小E心中分量越重的人,收到的礼物会越多。小E从商店中购买了n件礼物,打算送给m个人
    ,其中送给第i个人礼物数量为wi。请你帮忙计算出送礼物的方案数(两个方案被认为是不同的,当且仅当存在某
    个人在这两种方案中收到的礼物不同)。由于方案数可能会很大,你只需要输出模P后的结果。

    Input

    输入的第一行包含一个正整数P,表示模;
    第二行包含两个整整数n和m,分别表示小E从商店购买的礼物数和接受礼物的人数;
    以下m行每行仅包含一个正整数wi,表示小E要送给第i个人的礼物数量。

    Output

    若不存在可行方案,则输出“Impossible”,否则输出一个整数,表示模P后的方案数。

    Sample Input

    100
    4 2
    1
    2

    Sample Output

    12

    【样例说明】
    下面是对样例1的说明。
    以“/”分割,“/”前后分别表示送给第一个人和第二个人的礼物编号。12种方案详情如下:
    1/23 1/24 1/34
    2/13 2/14 2/34
    3/12 3/14 3/24
    4/12 4/13 4/23

    【数据规模和约定】
    设P=p1^c1 * p2^c2 * p3^c3 * … *pt ^ ct,pi为质数。
    对于100%的数据,1≤n≤109,1≤m≤5,1≤pi^ci≤10^5。
     
    题解Here!
    很容易就可以推出一个式子:
    ans=Cnw1+C(n-w1)w2+C(n-w1-w2)w3+... (mod p)
    由于p不一定是质数,所以用扩展Lucas即可。
    附代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    using namespace std;
    inline long long read(){
    	long long date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    long long mexp(long long a,long long b,long long c){
    	long long s=1;
    	while(b){
    		if(b&1)s=s*a%c;
    		a=a%c*a%c;
    		b>>=1;
    	}
    	return s;
    }
    void exgcd(long long a,long long b,long long &x,long long &y){
        if(!b){
            x=1;y=0;
            return;
        }
        exgcd(b,a%b,y,x);
        y-=a/b*x;
    }
    long long inv(long long a,long long c){
        if(!a)return 0;
        long long x=0,y=0;
        exgcd(a,c,x,y);
        return (x%c+c)%c;
    }
    long long mul(long long a,long long p,long long k){
        if(!a)return 1;
        long long s=1;
        if(a/k){
            for(long long i=2;i<k;i++)if(i%p)s=s*i%k;
            s=mexp(s,a/k,k);
        }
        for(long long i=2;i<=a%k;i++)if(i%p)s=s*i%k;
        return s*mul(a/p,p,k)%k;
    }
    long long C(long long n,long long m,long long mod,long long p,long long k){
        if(n<m)return 0;
        long long a=mul(n,p,k),b=mul(m,p,k),c=mul(n-m,p,k);
    	long long q=0,s;
        for(long long i=n;i;i/=p)q+=i/p;
        for(long long i=m;i;i/=p)q-=i/p;
        for(long long i=n-m;i;i/=p)q-=i/p;
        s=a*inv(b,k)%k*inv(c,k)%k*mexp(p,q,k)%k;
        return s*(mod/k)%mod*inv(mod/k,k)%mod;
    }
    long long exlucas(long long n,long long m,long long mod){
        long long ans=0,x=mod;
        for(long long i=2;i*i<=mod;i++)
        if(x%i==0){
            long long k=1;
            while(x%i==0){
                k*=i;
                x/=i;
            }
            ans=(ans+C(n,m,mod,i,k))%mod;
        }
        if(x>1)ans=(ans+C(n,m,mod,x,x))%mod;
        return ans;
    }
    int main(){
    	int n,m,p;
    	long long ans=1,sum=0,val[10];
    	p=read();
    	n=read();m=read();
    	for(int i=1;i<=m;i++){
    		val[i]=read();
    		sum+=val[i];
    	}
    	if(sum>n){
    		printf("Impossible
    ");
    		return 0;
    	}
    	sum=n;
    	for(int i=1;i<=m;i++){
    		ans=ans*exlucas(sum,val[i],p)%p;
    		sum-=val[i];
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
     
     
  • 相关阅读:
    x64 平台开发 Mapxtreme 编译错误
    hdu 4305 Lightning
    Ural 1627 Join(生成树计数)
    poj 2104 Kth Number(可持久化线段树)
    ural 1651 Shortest Subchain
    hdu 4351 Digital root
    hdu 3221 Bruteforce Algorithm
    poj 2892 Tunnel Warfare (Splay Tree instead of Segment Tree)
    hdu 4031 Attack(BIT)
    LightOJ 1277 Looking for a Subsequence
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9000092.html
Copyright © 2011-2022 走看看