zoukankan      html  css  js  c++  java
  • 【BZOJ2142】礼物(拓展卢卡斯定理)

    【BZOJ2142】礼物(拓展卢卡斯定理)

    题面

    BZOJ
    洛谷

    题解

    显然如果(sum w_i>n)无解。
    否则答案就是:(displaystyle prod_{i=1}^m{n-sum_{j=0}^{i-1}w_jchoose w_i})
    因为并没有保证(P)是质数,所以需要用到拓展卢卡斯。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define ll long long
    ll sum;
    int P,n,m,M[50],V[50],w[50];
    int fpow(int a,int b)
    {
    	int s=1;
    	while(b){if(b&1)s*=a;a*=a;b>>=1;}
    	return s;
    }
    int fpow(int a,int b,int MOD)
    {
    	int s=1;
    	while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}
    	return s;
    }
    void exgcd(int a,int b,int &x,int &y)
    {
    	if(b==0){x=1;y=0;return;}
    	exgcd(b,a%b,y,x);y-=a/b*x;
    }
    int inv(int a,int b)
    {
    	int x,y;exgcd(a,b,x,y);
    	x=(x%b+b)%b;return x;
    }
    int fac[50],pw[50],tot;
    int JC(int n,int p,int MOD,int &z)
    {
    	if(!n){z=0;return 1;}
    	int ret=JC(n/p,p,MOD,z);z+=n/p;
    	int s=1;
    	if(n>=MOD)
    	{
    		for(int i=1;i<=MOD;++i)if(i%p)s=1ll*s*i%MOD;
    		s=fpow(s,n/MOD,MOD);n%=MOD;
    	}
    	for(int i=1;i<=n;++i)if(i%p)s=1ll*s*i%MOD;
    	ret=1ll*ret*s%MOD;
    	return ret;
    }
    int CRT()
    {
    	for(int i=2;i<=tot;++i)
    	{
    		int x,y;exgcd(M[1],M[i],x,y);
    		x=(1ll*x*(V[i]-V[1])%M[i]+M[i])%M[i];
    		V[1]=(V[1]+1ll*x*M[1])%(M[1]*M[i]);
    		M[1]*=M[i];
    	}
    	return V[1];
    }
    int main()
    {
    	scanf("%d%d%d",&P,&n,&m);
    	for(int i=1;i<=m;++i)scanf("%d",&w[i]),sum+=w[i];
    	if(sum>n){puts("Impossible");return 0;}
    	for(int i=2;i*i<=P;++i)
    		if(P%i==0)
    		{
    			fac[++tot]=i;
    			while(P%i==0)++pw[tot],P/=i;
    		}
    	if(P>1)fac[++tot]=P,pw[tot]=1;
    	for(int i=1;i<=tot;++i)
    	{
    		int N=n,zero=0,z=0,a=1,b=1,MOD=fpow(fac[i],pw[i]);
    		a=JC(N,fac[i],MOD,z);zero+=z;
    		b=JC(N-sum,fac[i],MOD,z);zero-=z;
    		for(int j=1;j<=m;++j)
    			b=1ll*b*JC(w[j],fac[i],MOD,z)%MOD,zero-=z;
    		M[i]=MOD;V[i]=1ll*a*inv(b,MOD)%MOD*fpow(fac[i],zero,MOD)%MOD;
    	}
    	printf("%d
    ",CRT());
    }
    
  • 相关阅读:
    消息中间件(一)MQ详解及四大MQ比较
    SIP协议
    PAT (Basic Level) Practice 1008 数组元素循环右移问题
    LeetCode-Algorithms 1. 两数之和
    PAT (Basic Level) Practice 1040 有几个PAT
    PAT (Basic Level) Practice 1023 组个最小数
    PAT (Basic Level) Practice 1021 个位数统计
    PAT (Basic Level) Practice 1007 素数对猜想
    PAT (Basic Level) Practice 1006 换个格式输出整数
    PAT (Basic Level) Practice 1004 成绩排名
  • 原文地址:https://www.cnblogs.com/cjyyb/p/10175432.html
Copyright © 2011-2022 走看看