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

除法取模练习(51nod 1119)

时间:2016-07-30 00:22:06      阅读:265      评论:0      收藏:0      [点我收藏+]

标签:

题目:1119 机器人走方格 V2

思路:求C(m+n-2,n-1) % 10^9 +7       (2<=m,n<= 1000000)

   在求组合数时,一般都通过双重for循环c[i][j] = c[i-1][j] + c[i-1][j-1]直接得到。

   但是m,n都很大时,就会超时。

   

   利用公式:C(n,r) = n! / r! *(n-r)!  与  a/b = x(mod M)  ->  a * (b ^ (M-2)) =x (mod M)     进行求解

 

费马小定理:对于素数 M 任意不是 M 的倍数的 b,都有:b ^ (M-1) = 1 (mod M)

a/b = x(mod M)  ->  a * (b ^ (M-2)) =x (mod M)的推导:

  只要 M 是一个素数,而且 b 不是 M 的倍数,就可以用一个逆元整数 b’,通过 a / b = a * b‘ (mod M),来以乘换除。

  a/b = x(mod M)

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

  而b ^ (M-2) mod M 就是逆元整数 b`。

 

所以最终要求的 x = n! *[r! *(n-r)!]^(M-2)  (mod M)  

 

#include <cstdio>
#include <string>

const int mod = 1000000007;
const int maxN = 1e6;
long long c[maxN*2 +10];
int m,n;

void init(){
    c[0] = 0;
    c[1] = 1;
    for(int i =1; i <= maxN*2+5; i++)
        c[i+1] = (c[i] *(i+1) ) % mod;
}

long long pow(long long n,long long m)
{
    long long ans = 1;
    while(m > 0)
    {
        if(m & 1)ans = (ans * n) % mod;
        m = m >> 1;
        n = (n * n) % mod;
    }
    return ans;
}

int main(){
    init();
    while(~scanf("%d%d",&n,&m))
    {
        long long ans = c[n - 1 + m - 1];
        ans = (ans * pow(c[n-1],mod - 2)) % mod;
        ans = (ans * pow(c[m - 1] ,mod - 2)) % mod;
        printf("%lld\n",ans);
    }
    return 0;
}

 

除法取模练习(51nod 1119)

标签:

原文地址:http://www.cnblogs.com/yoyo-sincerely/p/5719883.html

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