Light OJ 1067 Combinations (乘法逆元)

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
时间: 2024-11-03 01:23:41

Light OJ 1067 Combinations (乘法逆元)的相关文章

light oj 1067 组合数取模

题目连接:http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=26784 题目: Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Description: Given n different objects, you want to take k of them. How many ways to can do it? F

(light oj 1102) Problem Makes Problem (组合数 + 乘法逆元)

题目链接:http://lightoj.com/volume_showproblem.php?problem=1102 As I am fond of making easier problems, I discovered a problem. Actually, the problem is 'how can you make n by adding k non-negative integers?' I think a small example will make things clea

Light OJ 1054 Efficient Pseudo Code 求n^m的约数和

题目来源:Light OJ 1054 Efficient Pseudo Code 题意:求n的m次这个数的所有的约数和 思路:首先对于一个数n = p1^a1*p2^a2*p3^a3*-*pk^ak  约束和s = (p1^0+p1^1+p1^2+-p1^a1)(p2^0+p2^1+p2^2+-p2^a2)-(pk^0+pk^1+pk^2+-pk^ak) 然后就是先求素数表 分解因子 然后求p1^0+p1^1+p1^2+-p1^a1 这是一个以1开始的等比数列 就是(1-q^n)/(1-q) 最

light oj 1236 【大数分解】

给定一个大数,分解质因数,每个质因子的个数为e1,e2,e3,--em, 则结果为((1+2*e1)*(1+2*e2)--(1+2*em)+1)/2. //light oj 1236 大数分解素因子 #include <stdio.h> #include <iostream> #include <string.h> #include <algorithm> #include <math.h> #include <ctype.h> #i

[2016-04-21][light]OJ[1234][Harmonic Number]

时间:2016-04-21 22:18:26 星期四 题目编号:[2016-04-21][light]OJ[1234][Harmonic Number] 题目大意:求∑nk=11kn∈(1,108),精确到10?8求∑k=1n1kn∈(1,108),精确到10?8 分析: 想法是打表,然后输出,但是直接打表会爆内存 解决办法,就是每隔100个来打表,节省1100的空间,然后从那个值开始计算到当前值解决办法,就是每隔100个来打表,节省1100的空间,然后从那个值开始计算到当前值 对应的整百就是n

HDU3037 Saving Beans(Lucas定理+乘法逆元)

题目大概问小于等于m个的物品放到n个地方有几种方法. 即解这个n元一次方程的非负整数解的个数$x_1+x_2+x_3+\dots+x_n=y$,其中0<=y<=m. 这个方程的非负整数解个数是个经典问题,可以+1转化正整数解的个数用插板法解决:$C_{y+n-1}^{n-1}=C_{y+n-1}^y$. 而0<=y<=m,最后的结果就是—— $$\sum_{i=0}^m C_{i+n-1}^i$$ $$C_{n-1}^0+C_{n}^1+C_{n+1}^2+\dots+C_{n-1

UVa 11174 (乘法逆元) Stand in a Line

题意: 有n个人排队,要求每个人不能排在自己父亲的前面(如果有的话),求所有的排队方案数模1e9+7的值. 分析: <训练指南>上分析得挺清楚的,把公式贴一下吧: 设f(i)为以i为根节点的子树的排列方法,s(i)表示以i为根的子树的节点总数. f(i) = f(c1)f(c2)...f(ck)×(s(i)-1)!/(s(c1)!s(c2)!...s(ck)!) 按照书上最开始举的例子,其实这个式子也不难理解,就是先给这些子树确定一下位置,即有重元素的全排列. 子树的位置确定好以后,然后再确定

Light OJ 1411 Rip Van Winkle`s Code 线段树成段更新

题目来源:Light OJ 1411 Rip Van Winkle`s Code 题意:3中操作 1种查询 求区间和 其中每次可以把一段区间从左到右加上1,2,3,...或者从右到左加上...3,2,1 或者把某个区间的数都置为v 思路:我是加了6个域 add是这段区间每个数都要加上add  add是这么来的 对与123456...这个等差数列 可能要分为2个区间 那么我就分成123和123 两个右边的等差数列每个数还应该加上3 所以右区间add加3 v是这个区间都要置为v 他的优先级最高 b是

LightOJ - 1050 (唯一分解+推公式+乘法逆元)

题意:求a^b的所有约数和对1e9+7取模的结果 思路:对于一个数p,进行唯一分解,则p=P1^M1*P2^M2*...*Pn^Mn,则p的所有约数之和等于(P1^0+P1^1+...+P1^M1)*(P2^0+P2^1+...+P2^M2)*...*(Pn^0+Pn^1+...+Pn^Mn), p^t=P1^(M1*t)*P2^(M2*t)*...*Pn^(Mn*t),每一个(Pn^0+Pn^1+...+Pn^Mn)利用等比数列可以直接推出公式为(Pn^(Mn*t+1)-1)/(Pn-1),用