恩恩。。。数论题目
首先答案即C(n, m) % p (其中p = 10007)
于是我们想到了Lucas定理(别问窝为什么,我是蒟蒻T T):C(n, m) % p = (C(n % p, m % p) * C(n / p, m / p)) % p
这里p很小,于是左半部分"C(n % p, m % p)"只要直接暴力求就可以了:
c(x, y) = x * (x - 1) * (x - 2) * ... * (x - y + 1) / (1 * 2 * 3 * ... * y)
被除的部分再求一下逆元就可以了,方法是费马小定理:
a ^ (p - 1) ≡ 1 (mod p) (其中p为质数) => a^-1 ≡ a ^ (p - 2) mod p
而右半部分"C(n / p, m / p)"直接递归下去就可以了。
好慢啊。。。20ms。。。别人都0ms的说。。。
1 /************************************************************** 2 Problem: 2982 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:20 ms 7 Memory:804 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <algorithm> 12 13 using namespace std; 14 typedef long long ll; 15 const int mod = 10007; 16 17 inline int read(){ 18 int x = 0; 19 char ch = getchar(); 20 while (ch < '0' || ch > '9') 21 ch = getchar(); 22 while (ch >= '0' && ch <= '9'){ 23 x = x * 10 + ch - '0'; 24 ch = getchar(); 25 } 26 return x; 27 } 28 29 inline int pow(int a, int b){ 30 int res = 1; 31 while (b){ 32 if (b & 1) res *= a, res %= mod; 33 a *= a, a %= mod; 34 b >>= 1; 35 } 36 return res; 37 } 38 39 int getc(int x, int y){ 40 if (x < y) return 0; 41 y = min(y, x - y); 42 int i; 43 ll res1 = 1, res2 = 1; 44 for (i = 0; i < y; ++i){ 45 res1 *= (x - i), res1 %= mod; 46 res2 *= (i + 1), res2 %= mod; 47 } 48 return res1 * pow(res2, mod - 2) % mod; 49 } 50 51 int Lucas(int x, int y){ 52 return !y ? 1 : (getc(x % mod, y % mod) * Lucas(x / mod, y / mod)) % mod; 53 } 54 55 int main(){ 56 int T = read(); 57 int x, y; 58 while (T--){ 59 x = read(), y = read(); 60 printf("%d ", Lucas(x, y)); 61 } 62 return 0; 63 }