1. 题目描述
题目很简单,就是求$C(n,m) % M$。
2. 基本思路
这是一道应用了众多初等数论定理的题目,因为数据范围较大因此使用Lucas求$C(n,m) % P$。
而M较大,因此通过$a[i] = C(n,m)%P_i$再综合中国剩余定理可解。由于数据可能为$10^{18}$,再进行乘法可能超long long。
因此,还需要模拟乘法。
3. 代码
1 /* 5446 */ 2 #include <iostream> 3 #include <sstream> 4 #include <string> 5 #include <map> 6 #include <queue> 7 #include <set> 8 #include <stack> 9 #include <vector> 10 #include <deque> 11 #include <bitset> 12 #include <algorithm> 13 #include <cstdio> 14 #include <cmath> 15 #include <ctime> 16 #include <cstring> 17 #include <climits> 18 #include <cctype> 19 #include <cassert> 20 #include <functional> 21 #include <iterator> 22 #include <iomanip> 23 using namespace std; 24 //#pragma comment(linker,"/STACK:102400000,1024000") 25 26 #define sti set<int> 27 #define stpii set<pair<int, int> > 28 #define mpii map<int,int> 29 #define vi vector<int> 30 #define pii pair<int,int> 31 #define vpii vector<pair<int,int> > 32 #define rep(i, a, n) for (int i=a;i<n;++i) 33 #define per(i, a, n) for (int i=n-1;i>=a;--i) 34 #define clr clear 35 #define pb push_back 36 #define mp make_pair 37 #define fir first 38 #define sec second 39 #define all(x) (x).begin(),(x).end() 40 #define SZ(x) ((int)(x).size()) 41 #define lson l, mid, rt<<1 42 #define rson mid+1, r, rt<<1|1 43 44 typedef long long LL; 45 const int maxn = 1e5+15; 46 LL fact[maxn]; 47 LL P[15], a[15]; 48 LL n, m; 49 int k; 50 51 void init_fact(LL mod) { 52 fact[0] = 1; 53 rep(i, 1, maxn) fact[i] = fact[i-1] * i % mod; 54 } 55 56 LL Pow(LL base, LL n, LL mod) { 57 LL ret = 1; 58 59 while (n) { 60 if (n & 1) 61 ret = ret * base % mod; 62 base = base * base % mod; 63 n >>= 1; 64 } 65 66 return ret; 67 } 68 69 inline LL Inv(LL a, LL mod) { 70 return Pow(a, mod-2, mod); 71 } 72 73 LL C(LL n, LL m, LL mod) { 74 if (n < m) return 0; 75 #ifndef ONLINE_JUDGE 76 assert(n >= m); 77 #endif 78 return fact[n] * Inv(fact[n-m]*fact[m]%mod, mod) % mod; 79 } 80 81 LL Lucas(LL n, LL m, LL mod) { 82 if (m == 0) return 1; 83 return C(n%mod, m%mod, mod) * Lucas(n/mod, m/mod, mod) % mod; 84 } 85 86 void egcd(LL a, LL b, LL& d, LL& x, LL& y) { 87 if (!b) { 88 d = a; 89 x = 1; 90 y = 0; 91 } else { 92 egcd(b, a%b, d, y, x); 93 y -= a/b * x; 94 } 95 } 96 97 LL Mul(LL base, LL n, LL mod) { 98 LL ret = 0; 99 100 while (n) { 101 if (n & 1) 102 ret = (ret + base) % mod; 103 base = (base + base) % mod; 104 n >>= 1; 105 } 106 107 return ret; 108 } 109 110 LL china(int n, LL *a, LL *m) { 111 LL M = 1, w, d, x = 0, y; 112 LL tmp; 113 bool sign; 114 115 rep(i, 0, n) M *= m[i]; 116 rep(i, 0, n) { 117 w = M/m[i]; 118 egcd(m[i], w, d, d, y); 119 sign = y < 0; 120 tmp = Mul(w, abs(y), M); 121 tmp = Mul(tmp, a[i], M); 122 if (sign) tmp = -tmp; 123 x = (x + tmp) % M; 124 } 125 126 return (x + M) % M; 127 } 128 129 void solve() { 130 rep(i, 0, k) { 131 init_fact(P[i]); 132 a[i] = Lucas(n, m, P[i]); 133 } 134 135 LL ans = china(k, a, P); 136 printf("%I64d\n", ans); 137 } 138 139 int main() { 140 cin.tie(0); 141 ios::sync_with_stdio(false); 142 #ifndef ONLINE_JUDGE 143 freopen("data.in", "r", stdin); 144 freopen("data.out", "w", stdout); 145 #endif 146 147 int t; 148 149 scanf("%d", &t); 150 while (t--) { 151 scanf("%I64d%I64d%d", &n,&m,&k); 152 rep(i, 0, k) 153 scanf("%I64d", &P[i]); 154 solve(); 155 } 156 157 #ifndef ONLINE_JUDGE 158 printf("time = %ldms.\n", clock()); 159 #endif 160 161 return 0; 162 }
时间: 2024-12-19 14:13:39