码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ.2142.礼物(扩展Lucas)

时间:2018-03-22 23:50:37      阅读:190      评论:0      收藏:0      [点我收藏+]

标签:pre   std   alc   www.   strong   ++i   注意   优化   down   

题目链接

答案就是C(n,m1) * C(n-m1,m2) * C(n-m1-m2,m3)...(mod p)
使用扩展Lucas求解。
一个很简单的优化就是把pi,pi^ki次方存下来,因为每次分解p都是很慢的。
注意最后p不为1要把p再存下来!(质数)

COGS 洛谷上的大神写得快到飞起啊QAQ 就这样吧

//836kb 288ms
#include <cmath>
#include <cstdio>
typedef long long LL;

int cnt,P[500],PK[500];
LL FP(LL x,int k,LL p)
{
    LL t=1ll;
    for(; k; k>>=1,x=x*x%p)
        if(k&1) t=t*x%p;
    return t;
}
LL Exgcd(LL a,LL b,LL &x,LL &y)
{
    if(!b) x=1,y=0;
    else Exgcd(b,a%b,y,x),y-=a/b*x;
}
LL Inv(LL a,LL p)
{
    LL x,y; Exgcd(a,p,x,y);
    return (x%p+p)%p;
}
LL Fact(LL x,LL pi,LL pk)//Calc x! % (pk=pi^ki)(x!中无pi因子)
{
    if(!x) return 1ll;
    LL res=1ll;
    if(x>=pk)
    {
        for(int i=2; i<pk; ++i)//从1开始没什么用 
            if(i%pi) (res*=i)%=pk;//无pi因子!
        res=FP(res,x/pk,pk);
    }
    for(int i=2; i<=x%pk; ++i)
        if(i%pi) (res*=i)%=pk;
    return res*Fact(x/pi,pi,pk)%pk;
}
int C(LL n,LL m,LL pi,LL pk,LL mod)//int
{
    if(n<m) return 0;
    LL a=Fact(n,pi,pk),b=Fact(m,pi,pk),c=Fact(n-m,pi,pk);int k=0;
    for(LL i=n; i; i/=pi) k+=i/pi;
    for(LL i=m; i; i/=pi) k-=i/pi;
    for(LL i=n-m; i; i/=pi) k-=i/pi;
    LL res=a*Inv(b,pk)%pk*Inv(c,pk)%pk*FP(pi,k,pk)%pk;
    return res*(mod/pk)%mod*Inv(mod/pk,pk)%mod;
}
LL Solve(int n,int m,int p)
{
    if(!n) return 1ll;
    int res=0;
    for(int i=1; i<=cnt; ++i) (res+=C(n,m,P[i],PK[i],p))%=p;
    return (LL)res;
}

int main()
{
    int n,m,p,t[9];
    scanf("%d%d%d",&p,&n,&m);
    int sum=0;
    for(int i=1; i<=m; ++i) scanf("%d",&t[i]),sum+=t[i];
    if(sum>n) {puts("Impossible"); return 0;}
    int now=p;
    for(int i=2,lim=sqrt(p+0.5); i<=lim; ++i)
        if(!(now%i))
        {
            int pk=1;
            while(!(now%i)) now/=i,pk*=i;
            P[++cnt]=i, PK[cnt]=pk;
            if(now==1) break;
        }
    if(now!=1) P[++cnt]=now,PK[cnt]=now;
    LL res=1ll;
    for(int i=1; i<=m; ++i) (res*=Solve(n,t[i],p))%=p,n-=t[i];
    printf("%lld",res);

    return 0;
}

BZOJ.2142.礼物(扩展Lucas)

标签:pre   std   alc   www.   strong   ++i   注意   优化   down   

原文地址:https://www.cnblogs.com/SovietPower/p/8627539.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!