【题目描述】

商店里出售n种花,现打算购买m支花,每种花最多购买1支,询问有多少种购买方案,输出方案数 mod p的值。

【输入描述】

输入三个整数n、m、p。

【输出描述】

输出一个整数,表示答案。

【输入样例】

4 2 5

【输出样例】

1

【数据范围及提示】

样例中,若用数字1、2、3、4来表示花的种类,4种花里购买各不相同的2支的方案有(1,2)、(1,3)、(1,4)、(2,3)、(2,4)、(3,4),共6种方案,模5后为1。

对于30%的数据,n,m ≤ 10;

对于50%的数据,n,m ≤ 1000;

对于80%的数据,1 ≤ m ≤n ≤ 50000;

对于100%的数据,1 ≤ m ≤ n ≤ 1000000,p ≤ 1000000000。

源代码:

#include<cstdio>
#include<cmath>
#define LL long long
LL m,n,INF,Num(0),Ans=1,Sum[350000]={0},Prime[350000];
bool Vis[1000001]={0};
LL Count(LL S,LL X)
{
    LL Number=1;
    while (S)
    {
        if (S&1)
          Number=Number*X%INF;
        X=X*X%INF;
        S>>=1;
    }
    return Number;
}
void Euler()
{
    LL t=n;
    for (LL a=2;a<=t;a++)
    {
        if (!Vis[a])
          Prime[Num++]=a;
        for (LL b=0;b<Num&&a*Prime[b]<=t;b++)
        {
            Vis[a*Prime[b]]=true;
            if (!(a%Prime[b]))
              break;
        }
    }
}
int main() //老办法。
{
    scanf("%lld%lld%lld",&n,&m,&INF);
    Euler();
    for (LL a=0;a<Num;a++)
    {
        LL t=n;
        while (t)
        {
            Sum[a]+=t/Prime[a];
            t/=Prime[a];
        }
    }
    n-=m;
    for (LL a=0;a<Num;a++)
    {
        LL t=n;
        while (t)
        {
            Sum[a]-=t/Prime[a];
            t/=Prime[a];
        }
    }
    for (LL a=0;a<Num;a++)
    {
        LL t=m;
        while (t)
        {
            Sum[a]-=t/Prime[a];
            t/=Prime[a];
        }
    }
    for (LL a=0;a<Num;a++)
      if (Sum[a])
        Ans=Count(Sum[a],Prime[a])%INF*Ans%INF;
    printf("%lld",Ans);
    return 0;
}
原文地址:https://www.cnblogs.com/Ackermann/p/5968856.html