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

Light OJ 1067 Combinations (乘法逆元)

时间:2015-07-18 02:02:17      阅读:210      评论:0      收藏:0      [点我收藏+]

标签:

Description

Given n different objects, you want to take k of them. How many ways to can do it?

For example, say there are 4 items; you want to take 2 of them. So, you can do it 6 ways.

Take 1, 2

Take 1, 3

Take 1, 4

Take 2, 3

Take 2, 4

Take 3, 4

Input

Input starts with an integer T (≤ 2000), denoting the number of test cases.

Each test case contains two integers n (1 ≤ n ≤ 106), k (0 ≤ k ≤ n).

Output

For each case, output the case number and the desired value. Since the result can be very large, you have to print the result modulo 1000003.

Sample Input

3

4 2

5 0

6 4

Sample Output

Case 1: 6

Case 2: 1

Case 3: 15

知识点:乘法逆元,扩展欧几里得。

题意:求C(n,m)%mod

难点:理解乘法逆元。

扩展:乘法逆元定义:如果a*b=1(mod n),那么b就是a关于模n的乘法逆元,此时,也可称作a与b互为乘法逆元。

思路:1.C(n,m)%mod=n!/m!*(n-m)!%mod除以一个数并取模等价于乘以这个数的逆元然后再去模.可将n!/m!*(n-m)!%mod等价于n!/m!%mod*1/(n-m)!%mod.再等价于n!*inv[m!]%mod(m!的逆元)*inv[(n-m)!]((n-m!)的逆元).

         2.也就是说,求出逆元即可求解。c*x=1(mod n)=1-k*n等价于c*x+k*n=1所以可以用扩展欧几里得算法求得x(逆元)的值。为了保证x是正整数,通常需要加上:x=(x%n+n)%n.

 1 #include<cstdlib>
 2 #include<cstdio>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cstring>
 6 using namespace std;
 7 #define m 1000003
 8 long long  f[1000005];
 9 long long inv[1000005];
10 long long x,y,gcd;
11 void extend_gcd(long long  a, long long b)
12 {
13     if(b == 0)
14     {
15         x = 1;
16         y = 0;
17         gcd = a;
18     }
19     else {
20         extend_gcd(b, a%b);
21         long long temp = x;
22         x = y;
23         y = temp - a/b*y;
24     }
25 }
26 void factorial()
27 {
28     f[0]=1;inv[0]=1;
29     for(int i=1;i<=1000000;i++)
30     {
31        f[i]=f[i-1]*i%m;
32        extend_gcd(f[i],m);
33        inv[i]=(x%m+m)%m;
34     }
35 }
36 int main()
37 {
38     factorial();
39     int t;
40     int cnt=0;
41     scanf("%d\n",&t);
42     int a1,b1;
43     while(t--)
44     {
45        scanf("%d%d",&a1,&b1);
46        long long ans=f[a1]*inv[b1]%m*inv[a1-b1]%m;
47        printf("Case %d: %lld\n",++cnt,ans);
48 
49     }
50 
51  return 0;
52 }
53 //3
54 //
55 //4 2
56 //
57 //5 0
58 //
59 //6 4
60 
61 //3
62 //1 1
63 //2 3
64 //4 3

 

 

Light OJ 1067 Combinations (乘法逆元)

标签:

原文地址:http://www.cnblogs.com/ZP-Better/p/4655380.html

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