卢卡斯定理 洛谷p3807

来源:互联网 发布:mac把照片导出到桌面 编辑:程序博客网 时间:2024/06/04 00:52

题目背景

这是一道模板题。

题目描述

给定n,m,p(1≤n,m,p≤1051\le n,m,p\le 10^51n,m,p105)

Cn+mm mod pC_{n+m}^{m}\ mod\ pCn+mm mod p

保证P为prime

C表示组合数。

一个测试点内包含多组数据。

输入输出格式

输入格式:

第一行一个整数T(T≤10T\le 10T10),表示数据组数

第二行开始共T行,每行三个数n m p,意义如上

输出格式:

共T行,每行一个整数表示答案。

输入输出样例

输入样例#1:复制
21 2 52 1 5
输出样例#1:复制
33


方法一:卢卡斯定理

C(n, m) % p  =  C( n/ p, m / p ) * C( n%p, m%p) % p

#include<iostream>#define f(i,l,r) for(i=(l);i<=(r);i++)using namespace std;const int MAXN=100005;long long n,m,p;int T;long long fac[MAXN],inv[MAXN];inline void MakeTable(){int i;fac[0]=inv[0]=inv[1]=1;f(i,1,p){fac[i]=fac[i-1]*i%p;}f(i,2,p){inv[i]=(p-p/i*inv[p%i]%p)%p;}f(i,2,p){inv[i]=inv[i-1]*inv[i]%p;}}inline long long C(long long n,long long m){if(n<m) return 0;return fac[n]*inv[m]%p*inv[n-m]%p;}inline long long Lucas(long long n,long long m){if(!m) return 1;return C(n%p,m%p)*Lucas(n/p,m/p)%p;}int main(){ios::sync_with_stdio(false);int i,j;cin>>T;while(T--){cin>>n>>m>>p;MakeTable();n+=m;cout<<Lucas(n,m)<<endl;}return 0;}

方法二:质因数分解后约分。

#include<iostream>#include<cstring>#include<algorithm>#define f(i,l,r) for(i=(l);i<=(r);i++)using namespace std;const int MAXN=100005;int n,m,p,inp[MAXN],prime[MAXN],p_num;int ppr[MAXN],pos;long long ans;inline void MakeTable(){int i,j;f(i,2,MAXN){if(!inp[i]){prime[++p_num]=i;}for(j=1;j<=p_num&&1LL*i*prime[j]<MAXN;j++){inp[i*prime[j]]=1;if(i%prime[j]==0){break;}}}}inline void fen1(int tmp){int num=1;while(tmp!=1){if(tmp%prime[num]==0){while(tmp%prime[num]==0){tmp/=prime[num];ppr[num]++;}pos=max(pos,num);}num++;}}inline void fen2(int tmp){int num=1;while(tmp!=1){if(tmp%prime[num]==0){while(tmp%prime[num]==0){tmp/=prime[num];ppr[num]--;}pos=max(pos,num);}num++;}}inline long long Pow_mod(long long a,long long b,long long mod){long long res=1;for(;b;b>>=1,a=(a*a)%p){if(b&1) res=(res*a)%p;}return res;}int main(){ios::sync_with_stdio(false);int i,j,T;MakeTable();cin>>T;while(T--){pos=0;ans=1;cin>>n>>m>>p;f(i,n+1,n+m){fen1(i);}f(i,1,m){fen2(i);}f(i,1,pos){ans=ans*Pow_mod(prime[i],ppr[i],p)%p;}f(i,1,pos) ppr[i]=0;cout<<ans<<endl;}return 0;}