• 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;
    }
    
     
     
  • 相关阅读:
    服务控制器
    .Net Web项目安装包制作 (一)
    C#制作Windows service服务系列一:制作一个可安装、可启动、可停止、可卸载的Windows
    用Visual C#创建Windows服务程序
    插件的“动态替换”
    .Net Web项目安装包制作(三)补充说明
    .net打包/C#WinFrom程序打包
    C#制作Windows service服务系列三制作可控制界面的Windows服务(windows service)
    C#制作Windows service服务系列二演示一个定期执行的windows服务及调试
    .Net Web项目安装包制作 (二)数据库安装、其他组件的安装
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9000092.html
Copyright © 2020-2023  润新知