Problem Description
There is a very big garden at Raven’s residence. We regard the garden as an n*m rectangle. Raven’s house is at the top left corner, and the exit of the garden is at the bottom right. He can choose to take one step to only one direction (up, down, left or right) each time. Raven wants to go out of the garden as quickly as possible, so he wonders how many routes he could choose.
Raven knows there are many possible routes, so he only wants to know the number, which is the result that the total number of possible routes modes a given value p. He knows it is a simple question, so he hopes you may help him to solve it.
Input Details
The first line of the input contains an integer T, which indicates the number of test cases.
Then it is followed by three positive integers n, m and p (1 <= n, m, p <= 10^5), showing the length and width of the garden and p to be the mod of the result.
Output Details
For each case, output one number to show the result (the sum modes p).
Sample Input
3 2 2 5 2 6 16 6 6 24
Sample Output
2 6 12
//
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define bignum long long
const int maxn=200000;
//求C(a,b)%p p任意 a,b,p<=1e5 O(a)
//首先打出素数表
int flag[maxn],pri[maxn],pl;
void _prime()
{
for(int i=2;i<maxn;i++)
{
if(flag[i]==0) pri[pl++]=i;
for(int j=0;j<pl&&i*pri[j]<maxn;j++)
{
flag[i*pri[j]]=1;
if(i%pri[j]==0) break;
}
}
}
//计算n!包含素因子p个数
bignum pNumInN(bignum n,bignum p)
{
bignum cnt=0;
while(n)
{
cnt+=n/p;
n/=p;
}
return cnt;
}
//a^b %p
bignum powmod(bignum a,bignum b,bignum p)
{
if(b==0) return 1;
if(b==1) return a%p;
bignum tmp=powmod(a,b/2,p);
tmp=(tmp*tmp)%p;
if(b&1) return (tmp*a)%p;
return tmp;
}
//求C(a,b)%p p任意 a,b,p<=1e5
bignum Comb_Mod_P(bignum a,bignum b,bignum p)
{
bignum cnt=1;
for(int i=0;i<pl&&pri[i]<=a;i++)
{
int num=pNumInN(a,pri[i])-pNumInN(a-b,pri[i])-pNumInN(b,pri[i]);
cnt=(cnt*powmod(pri[i],num,p))%p;
}
return cnt;
}
int main()
{
_prime();
int ci;scanf("%d",&ci);
while(ci--)
{
bignum n,m,p;cin>>n>>m>>p;
cout<<Comb_Mod_P(n+m-2,m-1,p)<<endl;
}
return 0;
}
//当p可以分解成多个比较小的pi^k乘积的时候比较快
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define F 200
#define M 200010
long long m;//mod
long long mp[F],mr;
long long xa[F],xb[F],xc[F];
long long circle[M] = {1};
void divide_factor(long long x){
long long i,k;
k = (long long)sqrt((double)x) + 1;
mr = 0;
for(i = 2; i <= k && x != 1; i++)
if(x % i == 0){
++mr; mp[mr] = i; xc[mr] = 1;
while(x % i == 0){x /= i; xc[mr] = xc[mr]*i;}
}
if(x != 1){++mr; mp[mr] = xc[mr] = x;}
}
long long get_fct(long long x, long long y){
long long ret = 0;
while(x != 0){ret += (x/y); x /= y;}
return ret;
}
long long cnt_exp(long long x, long long y, long long z){
long long ret = 1;
while( y != 0){
if(y % 2 == 1) ret = (ret*x)%z;
x = (x*x)%z; y = y >> 1;
}
return ret;
}
long long extend_gcd(long long a, long long b, long long &x, long long &y, long long z){
long long i,tmp;
if(b == 0) {x = 1; y = 0; return a;}
i = extend_gcd(b,a%b,x,y,z);
tmp = x; x = y; y = (tmp-a/b*y)%z;
return i;
}
long long CRT(){
long long i;
long long ret = 0;
for(i = 1; i <= mr; i++){
long long x,y;
extend_gcd(m/xc[i],xc[i],x,y,xc[i]);
x = x % m;
ret = (ret + xb[i]*m/xc[i]*x)%m;
}
return (ret+m)%m;
}
long long reverse(long long a, long long b){
long long x,y;
extend_gcd(a,b,x,y,b);
return (x%b + b) % b;
}
long long cnt_c(long long nn, long long mm){
long long i,j,k;
divide_factor(m);
for(i = 1; i <= mr; i++){
long long fct_num = get_fct(nn,mp[i])-get_fct(mm,mp[i])-get_fct(nn-mm,mp[i]);
for(j = 2,circle[1] = 1; j < xc[i]; j++)
if(j % mp[i] != 0) circle[j] = (circle[j-1]*j)%xc[i];
else circle[j] = circle[j-1];
xb[i] = 1; k = nn;
while(k != 0){
xb[i] = ( xb[i]*( (cnt_exp(circle[xc[i]-1],k/xc[i],xc[i])*circle[k-k/xc[i]*xc[i]])%xc[i] ) ) % xc[i];
k = k/mp[i];
}
for(j = 2,circle[1] = 1; j < xc[i]; j++ ){
if(j % mp[i] != 0) circle[j] = (circle[j-1]*reverse(j,xc[i]))%xc[i];
else circle[j] = circle[j-1];
}
k = mm;
while(k != 0){
xb[i] = ( xb[i]*( (cnt_exp(circle[xc[i]-1],k/xc[i],xc[i])*circle[k-k/xc[i]*xc[i]])%xc[i] ) ) % xc[i];
k = k/mp[i];
}
k = nn-mm;
while(k != 0){
xb[i] = ( xb[i]*( (cnt_exp(circle[xc[i]-1],k/xc[i],xc[i])*circle[k-k/xc[i]*xc[i]])%xc[i] ) ) % xc[i];
k = k/mp[i];
}
while(fct_num--) xb[i] = (xb[i]*mp[i])%xc[i];
}
return CRT();
}
int main()
{
int ci;scanf("%d",&ci);
while(ci--)
{
long long tn,tm,tp;cin>>tn>>tm>>tp;
m=tp;
cout<<cnt_c(tn+tm-2,tm-1)<<endl;
}
return 0;
}