组合数
TimeLimit: 1 Second MemoryLimit: 32 Megabyte
Totalsubmit: 58 Accepted: 4
Description
从A+B个不同的物品中选择A个物品,共有多少种不同的选法。由于A,B会很大,所以结果对C取下余。
Input
首先输入T,代表共有T组测试数据。
每组数据包括三个数字,A,B,C;
Output
输出只有一个数,如题目描述。
Sample Input
2
1 1 100
2 2 100
Sample Output
2
6
开始我以为一个简单的递归就可可以过,也就是C(n,m)=C(n-1,m)+C(n-1,m-1)组合数公式,但却tle;因为题目已经说明AB会很大,那么递归与暴力枚举是不可能AC的,那么该怎么做呢?:利用素数求法:
1 #include <stdio.h>
2 #include <string.h>
3 #include <math.h>
4
5 #define LEN 100000
6 #define PLEN 9592
7
8 void sieve ( char * f, int l ) {
9 int i, j, ilim;
10
11 memset ( f, 0x01, l );
12 f[0] = f[1] = 0;
13 ilim = ( int ) sqrt ( ( double ) l );
14
15 for ( i = 2; i <= ilim; ++i ) {
16 if ( !f[i] ) continue;
17 for ( j = i * i; j < l; j += i ) f[j] = 0;
18 }
19 }
20
21 char f[LEN];
22 int p[PLEN];
23 int u[PLEN], da[PLEN], db[PLEN];
24
25 void factor ( int n, int * r )
26 {
27 int i, j;
28 memset ( r, 0x00, PLEN * sizeof ( int ) );
29 for ( i = 0; i < PLEN; ++i )
30 {
31 for ( j = n; j; r[i] += ( j /= p[i] ) );
32 }
33 }
34
35 int main ( ) {
36 int i, j, k;
37 int T, A, B, C;
38
39 sieve ( f, LEN );
40 for ( i = 2, j = 0; i < LEN; ++i ) if ( f[i] ) p[j++] = i;//p[i]初始化
41 for(int i=0;i<20;i++)printf("%d ",p[i]);
42 for ( scanf ( "%d", &T ); T--; ) {
43 scanf ( "%d%d%d", &A, &B, &C );
44 factor ( A , u );
46 factor ( A, da );
47 factor ( B, db );
48 for ( i = 0, j = 1; i < PLEN; ++i ) {
49 k = u[i] - da[i] - db[i];
50 while ( k-- ) j = j * p[i] % C;
51 }
52 printf ( "%d /n", j );
53 }
54
55 return 0;
56 }