一本通1659礼物

2142: 礼物

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。
 
sol:这道题不就是一个ExLucas板子吗,然后码+调了一年
Ps:我太菜了
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
    ll s=0;
    bool f=0;
    char ch=' ';
    while(!isdigit(ch))
    {
        f|=(ch=='-'); ch=getchar();
    }
    while(isdigit(ch))
    {
        s=(s<<3)+(s<<1)+(ch^48); ch=getchar();
    }
    return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
    if(x<0)
    {
        putchar('-'); x=-x;
    }
    if(x<10)
    {
        putchar(x+'0'); return;
    }
    write(x/10);
    putchar((x%10)+'0');
    return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
ll n,m,Sum;
ll Num[10];
ll cnt=0,Mo[65],Yu[65];
ll prim[65],T[65];

inline ll Ksm(ll x,ll y,ll Pk);
inline ll C(ll n,ll m,ll P,ll Pk);
inline ll Solve();
inline void Exgcd(ll a,ll b,ll &X,ll &Y);
inline ll Jiecheng(ll n,ll P,ll Pk);
inline ll Exlucas(ll n,ll m,ll Mod);
inline ll Inv(ll Num,ll Mod);

inline ll Ksm(ll x,ll y,ll Pk)
{
    ll Ans=1;
    while(y)
    {
        if(y&1) Ans=Ans*x%Pk;
        x=x*x%Pk;
        y>>=1;
    }
    return Ans;
}
inline void Exgcd(ll a,ll b,ll &X,ll &Y)
{
    if(b==0)
    {
        X=1;
        Y=0;
        return;
    }
    Exgcd(b,a%b,X,Y);
    ll XX=X,YY=Y;
    X=YY;
    Y=XX-a/b*YY;
    return;
}
inline ll Inv(ll Num,ll Mod) //Num*Inv = 1 (%Mod)
{
    ll a=Num,b=Mod,c=1,X,Y;
    Exgcd(a,b,X=0,Y=0);
    return (X%b+b)%b;
}
inline ll Jiecheng(ll n,ll P,ll Pk)
{
    if(!n) return 1;
    ll i,Ans=1;
    for(i=2;i<=Pk;i++) if(i%P) Ans=Ans*i%Pk;
    Ans=Ksm(Ans,n/Pk,Pk);
    for(i=2;i<=n%Pk;i++) if(i%P) Ans=Ans*i%Pk;
    return Ans*Jiecheng(n/P,P,Pk)%Pk;
}
inline ll C(ll n,ll m,ll P,ll Pk)
{
    ll Jn=Jiecheng(n,P,Pk);
    ll Jm=Jiecheng(m,P,Pk);
    ll Jnm=Jiecheng(n-m,P,Pk);
    ll i,oo=0;
    for(i=n;i;i/=P) oo+=i/P;
    for(i=m;i;i/=P) oo-=i/P;
    for(i=n-m;i;i/=P) oo-=i/P;
    return Jn*Inv(Jm,Pk)%Pk*Inv(Jnm,Pk)%Pk*Ksm(P,oo,Pk)%Pk;
}
inline ll Exlucas(ll n,ll m,ll Mod)
{
    ll i,tmp=Mod;
    cnt=0;
    for(i=2;i<=sqrt(tmp);i++) if(tmp%i==0)
    {
        ll Num=1;
        while(tmp%i==0)
        {
            Num*=i;
            tmp/=i;
        }
        Mo[++cnt]=Num;
        Yu[cnt]=C(n,m,i,Num)%Num;
    }
    if(tmp>1)
    {
        Mo[++cnt]=tmp;
        Yu[cnt]=C(n,m,tmp,tmp)%tmp;
    }
    return Solve();
}
inline ll Solve()
{
    memmove(prim,Mo,sizeof Mo);
    memmove(T,Yu,sizeof T);
    int i;
    ll Lcm=prim[1];
    for(i=2;i<=cnt;i++)
    {
        ll a=prim[i-1],b=prim[i],c=T[i]-T[i-1],r=1,X,Y;
        Exgcd(a,b,X=0,Y=0);
        ll tmp=b/r;
        X=(X*c%tmp+tmp)%tmp;
        prim[i]=Lcm=Lcm*prim[i];
        T[i]=(X*prim[i-1]+T[i-1])%Lcm;
    }
    return T[cnt];
}
int main()
{
    ll Mod,i,Sum=0,ans=1;
    R(Mod);
    R(n); R(m);
    for(i=1;i<=m;i++) Sum+=(Num[i]=read());
    if(Sum>n) return 0*puts("Impossible");
    for(i=1;i<=m;i++)
    {
        ans=ans*Exlucas(n,Num[i],Mod)%Mod;
        n-=Num[i];
    }
    Wl(ans);
    return 0;
}
/*
input
286572286
843547440 1
262584859
output
44088044

input
100
4 2
1
2
output
12
*/
View Code

 

posted @ 2019-03-19 19:45  yccdu  阅读(279)  评论(0编辑  收藏  举报