HIT2813 Garden visiting(组合数)

给你三个整数 N、M、P,求组合数 C(N+M-2,M-1) % P。

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define ll long long

using namespace std;
const int maxn=200000+10;

bool isprime[maxn];
int prime[maxn];
int cnt=0,p;

void init()
{
    memset(isprime,0,sizeof(isprime));
    cnt=0;
    for(int i=2;i<=maxn;i++)
    {
        if(!isprime[i])
        {
            prime[cnt++]=i;
        }
        for(int j=0;j<cnt&&prime[j]<=maxn/i;j++)
        {
            isprime[prime[j]*i]=1;
            if(i%prime[j]==0)
                    break;
        }
    }
}

ll quick_pow(ll a,ll b,ll c)
{
    ll res=1,t;
    res=1;
    t=a%c;
    while(b)
    {
        if(b&1)
        {
            res=res*t%c;
        }
        t=t*t%c;
        b>>=1;
    }
    return res;
}

ll cal(ll n,ll p)
{
    ll ans=0;
    while(n){
        ans+=n/p;
        n/=p;
    }
    return ans;
}

ll C(ll n,ll m,ll p)
{
    long long ans=1;
    for(int i=0;i<cnt&&prime[i]<=n;i++)
    {
        long long c=cal(n,prime[i])-cal(m,prime[i])-cal(n-m,prime[i]);
        ans=ans*quick_pow(prime[i],c,p)%p;
    }
    return ans;
}

int T;
int n,m;

int main()
{
    init();
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&p);
        n+=m-2;
        m--;
        printf("%lld\n",C(n,m,p));
    }
    return 0;
}

 

posted @ 2018-10-16 17:05  Somnus、M  阅读(165)  评论(0编辑  收藏  举报