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

来源:互联网 发布:java自动包装功能 编辑:程序博客网 时间:2024/09/21 06:33

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

起点和终点之间确定一个矩形,(不包括起点和终点),设宽为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;     }     }}