zoukankan      html  css  js  c++  java
  • 「BZOJ 2142」礼物

    题目链接

    戳这

    Title Solution

    这一道题显然可以看出公式为:

    [ans=C_{n}^{w_1}*C_{n-w}^{w_2}*...*C_{w_m}^{w_m} ]

    然后就可以用扩展Lucas求解了。
    至于扩展Lucas:戳这

    code

    #include<bits/stdc++.h>
    #define rg register
    #define int long long
    #define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
    using namespace std;
    int read(){
        int x=0,f=1;
        char c=getchar();
        while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
        return f*x;
    }
    void exgcd(int a,int b ,int &x,int &y){
    
        if(!b){x=1,y=0;return;}
        exgcd(b,a%b,x,y);
        int t=x;
        x=y,y=t-(a/b)*y;
    }
    int inv(int a,int b){
        int x,y;
        return exgcd(a,b,x,y),(x%b+b)%b;
    }
    int ksm(int a,int b,int p){
        int ans=1;
        while(b){
            if(b&1)
                ans=a*ans%p;
            a=a*a%p;
            b>>=1;
        }
        return ans%p;
    }
    int crt(int x,int p,int mod){
        return inv(p/mod,mod)*(p/mod)*x;
    }
    int fac(int x,int a,int b){
        if(!x)
            return 1;
        int ans=1;
        for(int i=1;i<=b;i++)
            if(i%a)
                ans*=i,ans%=b;
        ans=ksm(ans,x/b,b);
        for(int i=1;i<=x%b;i++)
            if(i%a)
                ans*=i,ans%=b;
        return ans*fac(x/a,a,b)%b;
    }
    int C(int n,int m,int a,int b){
        int N=fac(n,a,b),M=fac(m,a,b),Z=fac(n-m,a,b),sum=0;
        for(int i=n;i;i=i/a)
            sum+=i/a;
        for(int i=m;i;i=i/a)
            sum-=i/a;
        for(int i=n-m;i;i=i/a)
            sum-=i/a;
        return N*ksm(a,sum,b)%b*inv(M,b)%b*inv(Z,b)%b;
    }
    int exlucas(int n,int m,int p){
        int t=p,ans=0;
        for(int i=2;i*i<=p;i++){
            int k=1;
            while(t%i==0)
                k*=i,t/=i;
            ans+=crt(C(n,m,i,k),p,k),ans%=p;
        }
        if(t>1)
            ans+=crt(C(n,m,t,t),p,t),ans%=p;
        return ans%p;
    }
    int a[11];
    void slove(){
        int p=read(),n=read(),m=read(),sum=0;
        for(int i=1;i<=m;i++)
            a[i]=read(),sum+=a[i];
        if(n<sum)
            printf("Impossible
    "),exit(0);
        int ans=1;
        for(int i=1;i<=m;i++)
            ans*=exlucas(n,a[i],p),ans%=p,n-=a[i];
        printf("%lld",ans%p);
    }
    main(){
        slove();
        return 0;
    }
    
  • 相关阅读:
    中国剩余定理及其扩展
    扩展欧几里得
    乘法逆元
    58-63用ssh远程连接linux系统
    148复习前一天的内容
    165-168函数
    Linux运维命令总结(-)
    177流程控制经典案例讲解
    170-176流程控制
    161【案例讲解】存储过程
  • 原文地址:https://www.cnblogs.com/hbxblog/p/10211424.html
Copyright © 2011-2022 走看看