• [BZOJ 2142]礼物(扩展Lucas定理)


    Description

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

    Solution

    扩展Lucas的板子题

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    using namespace std;
    typedef long long LL;
    LL Mod,n,m,w;
    LL read()
    {
        LL x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    LL pow(LL a,LL n,LL p)
    {
        LL res=1;
        while(n)
        {
            if(n&1)res=(res*a)%p;
            a=(a*a)%p,n>>=1;
        }
        return res;
    }
    void exgcd(LL a,LL b,LL &d,LL &x,LL &y)
    {
        if(!b)d=a,x=1,y=0;
        else exgcd(b,a%b,d,y,x),y-=x*(a/b);
    }
    LL inv(LL a,LL p)
    {
        LL d,x,y;exgcd(a,p,d,x,y);
        return (x+p)%p==0?p:(x+p)%p;
    }
    LL fac(LL n,LL p,LL pk)
    {
        if(n==0)return 1;
        LL res=1;
        for(LL i=2;i<=pk;i++)
            if(i%p)res=(res*i)%pk;
        res=pow(res,n/pk,pk);
        for(LL i=2;i<=n%pk;i++)
            if(i%p)res=(res*i)%pk;
        return (res*fac(n/p,p,pk))%pk;
    }
    LL C(LL n,LL m,LL p,LL pk)
    {
        if(n<m)return 0;
        LL a=fac(n,p,pk),b=fac(m,p,pk),c=fac(n-m,p,pk);
        LL k=0;
        for(LL i=n;i;i/=p)k+=i/p;
        for(LL i=m;i;i/=p)k-=i/p;
        for(LL i=n-m;i;i/=p)k-=i/p;
        LL res=(((a*inv(b,pk))%pk)*inv(c,pk))%pk*pow(p,k,pk)%pk;
        return res*(Mod/pk)%Mod*inv(Mod/pk,pk)%Mod;
    }
    LL Lucas(LL n,LL m)
    {
        LL res=0,P=Mod;
        for(LL i=2;i<=P;i++)
            if(P%i==0)
            {
                LL pk=1;
                while(P%i==0)P/=i,pk*=i;
                res=(res+C(n,m,i,pk))%Mod;
            }
        return res;
    }
    int main()
    {
        Mod=read(),n=read(),m=read();
        LL ans=1;
        for(int i=1;i<=m;i++)
        {
            w=read();
            if(n<w){printf("Impossible");return 0;}
            ans=(ans*Lucas(n,w))%Mod;
            n-=w;
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    L-这是最难的题(二分+前缀和)
    SPFA 原理剖析代码实现分析比较
    树状数组---原理代码实现
    bellman-ford算法
    UML用例图总结
    UML类图几种关系的总结
    UML序列图总结
    线段树--Color the ball(多次染色问题)
    临时文档3
    POJ2676-Sudoku(数独)
  • 原文地址:https://www.cnblogs.com/Zars19/p/6993918.html
Copyright © 2020-2023  润新知