toj 4111 组合数取模 暴力分解

题目大意:组合数取模,n和m并不算大,p比较大且是合数。

思路:暴力分解+快速幂

注:暴力也是有区别的,分解质因数时可以用以下work函数,写的非常巧妙,摘录自互联网。

 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 const ll mod = 1ll << 32;
 7 const int N = 1000001;
 8 const int M = 100007;
 9 bool is_prime[N];
10 int prime[M];
11 int p;
12 
13 void get()
14 {
15     memset( is_prime, true, sizeof(is_prime) );
16     is_prime[0] = is_prime[1] = false;
17     for ( int i = 2; i < N; i++ )
18     {
19         if ( is_prime[i] )
20         {
21             int j = i * i;
22             if ( j >= N ) break;
23             do
24             {
25                 is_prime[j] = false;
26                 j += i;
27             } while ( j < N );
28         }
29     }
30     p = 0;
31     for ( int i = 0; i < N; i++ )
32     {
33         if ( is_prime[i] )
34         {
35             prime[p++] = i;
36         }
37     }
38 }
39 
40 ll pow_mod( ll a, ll n )
41 {
42     ll ans = 1;
43     a = a % mod;
44     while ( n )
45     {
46         if ( n & 1 )
47         {
48             ans = ans * a % mod;
49         }
50         n = n >> 1;
51         a = a * a % mod;
52     }
53     return ans;
54 }
55 
56 ll work( ll n, ll q )
57 {
58     ll ans = 0;
59     while ( n )
60     {
61         ans += n / q;
62         n /= q;
63     }
64     return ans;
65 }
66 
67 ll c( ll n, ll m )
68 {
69     ll ans = 1;
70     for ( int i = 0; i < p && prime[i] <= n; i++ )
71     {
72         ll x = work( n, prime[i] );
73         ll y = work( n - m, prime[i] );
74         ll z = work( m, prime[i] );
75         x = x - ( y + z );
76         ans = ans * pow_mod( prime[i], x ) % mod;
77     }
78     return ans;
79 }
80 
81 int main ()
82 {
83     get();
84     int t;
85     cin >> t;
86     while ( t-- )
87     {
88         ll n, m;
89         cin >> n >> m;
90         cout << c( n, m ) << endl;
91     }
92     return 0;
93 }
posted @ 2015-04-16 23:23  hxy_has_been_used  阅读(187)  评论(0编辑  收藏  举报