HDU5698(排列组合 C(a,b)modP 模板 )

参考了较多的文章,就不一一附上链接了。

起点和终点之间确定一个矩形,(不包括起点和终点),设宽为N,高为M。

这最大可走步数 step=min(N,M) 

,对于走一步完成的只有一种情况,即t(1)=1

对于走两步完成的有 t(2)=C(N,1)*C(M,1)

对于走三步完成的有 t(3)=C(N,2)*C(M,2)

...........

接下来套用C(a,b)modP 模板 

这个地方涉及到 快速幂和逆元

C(a,b) mod P=a! / (a-b)!*b! 但是这样不能取模,采用逆元将 1/(a-b)! 转化为 (a-b)!^(P-2) mod P

1/b! 转化为 b!^(P-2) mod P 则 C(a,b) mod P=a! / (a-b)!*b! = a!*(a-b)!^(P-2) mod P * b!^(P-2) mod P

然后对(a-b)!^(P-2)和 b!^(P-2)进行快速幂 取模 求解即可。

下面AC的java代码

import java.util.Scanner;

public class Main 
{ 
	 public static final int MAX=100000;
	 public static final long MOD=1000000007;
	 public static long hie[]=new long [MAX+5];
	
	
     public static void main(String args[])
     {
    	 init();
    	 
    	 Scanner in=new Scanner(System.in);
    	 
    	 while(true)
    	 {
    		 int a,b;
    		 try 
    		 {
				a=in.nextInt();
    		    b=in.nextInt();
			 } 
    		 catch (Exception e) 
    		 {
				return ;
			 }
    		 
    		 long ans=1;
    		 a-=2;
    		 b-=2;
    		 
    		 for(int i=1;i<=Math.min(a,b);i++)
    		 {
    			 ans=(ans+CmodP(a,i,MOD)*CmodP(b,i,MOD))%MOD;
    		 }
    		 System.out.println(ans);
    	 }
      }
     
     public static long CmodP(int a,int b,long P)
     {
    	 if(a==b) return 1;
    	 return hie[a]*quickpowmod(hie[a-b],P-2)%MOD*quickpowmod(hie[b],P-2)%MOD;
     }
     
     public static long quickpowmod(long x,long y)
     {
    	 long D=1; 
    	 while(y>0)
    	 {
    		 if((1&y)==1)
    		 {
    			 D=D*x%MOD;	 
    		 }
    		 x=x*x%MOD;
    		 y>>=1;
    		
    	 }
    	 return D;
     }
      
     public static void init()
     {
    	 hie[1]=1;
    	 
    	 for(int i=2;i<=MAX;i++)
    	 {
    		 hie[i]=hie[i-1]*i%MOD;
    	 }
     }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值