码迷,mamicode.com
首页 > 其他好文 > 详细

HDU-4828 卡特兰数+带模除法

时间:2015-05-04 23:39:26      阅读:143      评论:0      收藏:0      [点我收藏+]

标签:

题意:给定2行n列的长方形,然后把1—2*n的数字填进方格内,保证每一行,每一列都是递增序列,求有几种放置方法,对1000000007取余;

思路:本来想用组合数找规律,但是找不出来,搜题解是卡特兰数,而且还有一个难点在于N的范围是1000000,卡特兰数早已数千位,虽然有取余;

解决方法就是用在求卡特兰数的时候快速取余+带模除法;

卡特兰数递归公式1:K(n)=K(n-1) * ((4*n-2)/(n+1)); 组合数公式2:K[n] = C[2*n][n] /(n+1);

看公式1,有个除法运算,K(n-1) * ((4*n-2)很大,无法直接求得K(n-1) * ((4*n-2)/(n+1))的值,因此需要求乘法逆元(满足a*k≡1 (mod p)的k值就是a关于p的乘法逆元,按  照倒数理解就好);

 求乘法逆元的方法:扩展欧几里得,费马小定理;

技术分享
 1 ///扩展欧几里得
 2 typedef long long LL ;
 3 LL exgcd(LL a,LL b,LL &x,LL &y)///使得ax+by==gcd(a,b);
 4 {
 5     if( b == 0 )
 6     {
 7         x = 1;
 8         y = 0;
 9         return a;
10     }
11     else
12     {
13         LL x1,y1;
14         LL d = exgcd ( b , a % b , x1 , y1 );
15         x = y1;
16         y= x1 - a / b * y1;
17         return d;
18     }
19 }
扩展GCD

费马小定理说,对于素数 M 任意不是 M 的倍数的 b,都有:

b ^ (M-1) = 1 (mod M)

于是可以拆成:

b * b ^ (M-2) = 1 (mod M)

于是:

a / b = a / b * (b * b ^ (M-2)) = a * (b ^ (M-2)) (mod M)

也就是说我们要求的逆元就是 b ^ (M-2) (mod M);

技术分享
 1 long long C[1000005] = {0LL};
 2 long long spow(long long x, int n)///递归
 3 {
 4     if (n == 1)
 5         return x;
 6     else
 7     {
 8         long long v = spow(x, n/2);
 9         if (n%2 == 0)
10             return v*v%MODLL;
11         else
12             return v*v%MODLL*x%MODLL;
13     }
14 }
费马小定理

 

HDU-4828 卡特兰数+带模除法

标签:

原文地址:http://www.cnblogs.com/ACMERY/p/4477669.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!