一、不取模直接运算。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#define ll long long
using namespace std;
const int maxn=62;
ll c[maxn][maxn];
ll _c[maxn][maxn];

ll C(ll n, ll m)
{
    ll res=1;
    for(ll i=1;i<=m;i++)
    {
        res=res*(n-m+i)/i;
    }
    return res;
}

int main(void)
{

    int n=maxn-1;

    for(int i=0;i<=n;i++)
    {
        c[i][0]=c[i][i]=1;
    }

    for(int i=2;i<=n;i++)
    {
        for(int j=1;j<=i/2;j++)
        {
            c[i][j]=c[i-1][j]+c[i-1][j-1];
            c[i][i-j]=c[i][j];
        }
    }

    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=i;j++)
            _c[i][j]=C(i,j);
    }


    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=i;j++)
        {
            printf("%lld,%lld ",c[i][j],_c[i][j]);
            //printf("c[%d][%d]:%lld _c[%d][%d]:%lld ",i,j,c[i][j],i,j,_c[i][j]);
        }
        putchar('\n');
        putchar('\n');
    }

    return 0;
}

二、取模运算:
①打表:
主要时间复杂度在O(n * n)。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#define ll long long
using namespace std;
const int maxn=1002;
ll c[maxn][maxn];
const ll mod=1000000007;

int main(void)
{

    int n=maxn-1;

    for(int i=0;i<=n;i++)
    {
        c[i][0]=c[i][i]=1;
    }

    for(int i=2;i<=n;i++)
    {
        for(int j=1;j<=i/2;j++)
        {
            c[i][j]=c[i-1][j]+c[i-1][j-1]%mod;
            c[i][i-j]=c[i][j];
        }
    }


    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=i;j++)
        {
            printf("%lld ",c[i][j]);
            //printf("c[%d][%d]:%lld _c[%d][%d]:%lld ",i,j,c[i][j],i,j,_c[i][j]);
        }
        putchar('\n');
        putchar('\n');
    }

    return 0;
}

②定义式计算:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#define ll long long
using namespace std;
const int maxn=1002;
const ll mod=1000000007;
const int maxx=100010;
int prime[maxx];
bool ha[maxx]={false};
int cnt=0;

void init(void)
{
    ha[1]=true;
    for(int i=2;i<maxx;i++)
    {
        if(!ha[i]) prime[cnt++]=i;
        for(int j=0;j<cnt&&prime[j]*i<maxx;j++)
        {
            ha[i*prime[j]]=true;
            if(i%prime[j]==0) break;
        }
    }
    return ;
}

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

ll mypow(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}


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

int main(void)
{
    init();

    for(int i=1;i<=maxn;i++)
    {
        for(int j=0;j<=i;j++)
        {
            printf("%lld ",C(i,j));
        }
        putchar('\n');
        putchar('\n');
    }
    return 0;
}

③定义式变形计算:
m<p,且p是素数。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#define ll long long
using namespace std;
const ll mod=1000000007;

ll mypow(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}


ll C(ll n,ll m)
{
    ll ans=1;
    for(int i=1;i<=m;i++)
    {
        ans=ans*(n-m+i)%mod;
        ans=ans*mypow(i,mod-2)%mod;
    }
    return ans;
}

int main(void)
{

    for(int i=1;i<=20;i++)
    {
        for(int j=0;j<=i;j++)
        {
            printf("%lld ",C(i,j));
        }
        putchar('\n');
        putchar('\n');
    }
    return 0;
}

m任意,p是素数

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#define ll long long
using namespace std;
const ll mod=113;

ll mypow(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}


ll C(ll n,ll m)
{
    ll ans=1;
    ll nump=0;
    for(int i=1;i<=m;i++)
    {
        ll temp=n-m+i;
        while(temp%mod==0)
        {
            nump++;
            temp/=mod;
        }
        ans=ans*temp%mod;

        temp=i;
        while(temp%mod==0)
        {
            nump--;
            temp/=mod;
        }
        ans=ans*mypow(temp,mod-2)%mod;
    }
    if(nump>0) return 0;
    return ans%mod;
}

int main(void)
{

    for(int i=1;i<=20;i++)
    {
        for(int j=0;j<=i;j++)
        {
            printf("%lld ",C(i,j));
        }
        putchar('\n');
        putchar('\n');
    }

    return 0;
}

m任意,p任意

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#define ll long long
using namespace std;
const ll mod=24;
const int maxn=100010;
int prime[maxn];
bool ha[maxn]={false};
ll p[200],e[200]={0};
int cnt=0,res=0;


void init(void)
{
    ha[1]=true;
    for(int i=2;i<maxn;i++)
    {
        if(!ha[i]) prime[cnt++]=i;
        for(int j=0;j<cnt&&i*prime[j]<maxn;j++)
        {
            ha[i*prime[j]]=true;
            if(i%prime[j]==0) break;
        }
    }
    return ;
}

void banf(ll n)
{
    for(int i=0;i<cnt&&prime[i]*prime[i]<=n;i++)
    {
        if(n%prime[i]) continue;
        p[++res]=prime[i];
        while(n%prime[i]==0) n/=prime[i];
    }
    if(n>1) p[++res]=n;
    return ;
}

ll mypow(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}

ll exgcd(ll a,ll b,ll &x,ll &y)
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }

    ll g=exgcd(b,a%b,x,y);
    ll z=x;
    x=y;
    y=z-a/b*y;
    return g;
}

ll inv(ll a,ll m)
{
    ll x,y;
    ll g=exgcd(a,m,x,y);
    return (x%m+m)%m;
}

ll C(ll n,ll m)
{
    ll ans=1;
    memset(e,0,sizeof(e));
    if(m==0) return 1;
    if(m==n) return 1;
    for(int i=1;i<=m;i++)
    {
        ll temp=n-m+i;

        for(int i=1;i<=res;i++)
        {
            while(temp%p[i]==0)
            {
                e[i]++;
                temp/=p[i];
            }
        }
        ans=ans*temp%mod;


        temp=i;
        for(int i=1;i<=res;i++)
        {
            while(temp%p[i]==0)
            {
                e[i]--;
                temp/=p[i];
            }
        }
        ans=ans*inv(temp,mod)%mod;
    }

    for(int i=1;i<=res;i++)
    {
        ans=ans*mypow(p[i],e[i])%mod;
    }
    memset(e,0,sizeof(e));
    return ans%mod;
}

int main(void)
{

    init();
    banf(mod);
    for(int i=1;i<=20;i++)
    {
        for(int j=0;j<=i;j++)
        {
            printf("%lld ",C(i,j));
        }
        putchar('\n');
        putchar('\n');
    }

    return 0;
}

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<map>
#define ll long long
using namespace std;
const ll mod=24;
const int maxn=100010;
int prime[maxn];
bool ha[maxn]={false};
int cnt=0;
map<ll,ll>mp;

void init(void)
{
    ha[1]=true;
    for(int i=2;i<maxn;i++)
    {
        if(!ha[i]) prime[cnt++]=i;
        for(int j=0;j<cnt&&i*prime[j]<maxn;j++)
        {
            ha[i*prime[j]]=true;
            if(i%prime[j]==0) break;
        }
    }
    return ;
}

void quanf(ll n)
{
    for(int i=0;i<cnt&&prime[i]*prime[i]<=n;i++)
    {
        if(n%prime[i]) continue;
        while(n%prime[i]==0)
        {
            mp[prime[i]]++;
            n/=prime[i];
        }
    }
    if(n>1) mp[n]++;
    return ;
}

void _quanf(ll n)
{
    for(int i=0;i<cnt&&prime[i]*prime[i]<=n;i++)
    {
        if(n%prime[i]) continue;
        while(n%prime[i]==0)
        {
            mp[prime[i]]--;
            n/=prime[i];
        }
    }
    if(n>1) mp[n]--;
    return ;
}

ll mypow(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}

ll C(ll n,ll m)
{
    ll ans=1;
    mp.clear();
    for(int i=1;i<=m;i++)
    {
        quanf(n-m+i);
        _quanf(i);
    }
    map<ll,ll>::iterator it;
    for(it=mp.begin();it!=mp.end();it++)
    {
        ans=ans*mypow(it->first,it->second);
    }
    return ans%mod;
}

int main(void)
{

    init();
    for(int i=1;i<=20;i++)
    {
        for(int j=0;j<=i;j++)
        {
            printf("%lld ",C(i,j));
        }
        putchar('\n');
        putchar('\n');
    }

    return 0;
}

④预处理阶乘和逆元:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<map>
#define ll long long
using namespace std;
const ll mod=13331;
const int maxn=10010;
ll jc[maxn],jc_inv[maxn];

ll mypow(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans%mod;
}

void init(void)
{
    jc[0]=jc_inv[0]=1;
    for(int i=1;i<maxn;i++)
    {
        jc[i]=(jc[i-1]*i)%mod;
        jc_inv[i]=mypow(jc[i],mod-2)%mod;
    }
}

ll C(ll n,ll m)
{
   return jc[n]*jc_inv[m]%mod*jc_inv[n-m]%mod;
}

int main(void)
{

    init();
    for(int i=1;i<=20;i++)
    {
        for(int j=0;j<=i;j++)
        {
            printf("%lld ",C(i,j));
        }
        putchar('\n');
        putchar('\n');
    }

    return 0;
}

⑤卢卡斯定理:
p是素数

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<map>
#define ll long long
using namespace std;
ll p;
ll mypow(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%p;
        a=a*a%p;
        b>>=1;
    }
    return ans%p;
}

ll C(ll n,ll m)
{
    ll ans=1;
    for(int i=1;i<=m;i++)
    {
        ans=(ans*(n-m+i))%p;
        ans=(ans*mypow(i,p-2))%p;
    }
    return ans%p;
}

ll Lucas(ll n,ll m)
{
    if(m==0) return 1;
    return C(n%p,m%p)%p*Lucas(n/p,m/p)%p;
}

int main(void)
{

    int t;
    cin>>t;
    while(t--)
    {
        ll n,m;
        scanf("%lld%lld%lld",&n,&m,&p);
        printf("%lld\n",Lucas(n,m));
    }

    return 0;
}