Description
曾经发明了脑洞治疗仪&超能粒子炮的发明家SHTSC又公开了他的新发明:超能粒子炮·改--一种可以发射威力更加
强大的粒子流的神秘装置。超能粒子炮·改相比超能粒子炮,在威力上有了本质的提升。它有三个参数n,k。它会
向编号为0到k的位置发射威力为C(n,k) mod 2333的粒子流。现在SHTSC给出了他的超能粒子炮·改的参数,让你求
其发射的粒子流的威力之和模2333。
Input
第一行一个整数t。表示数据组数。
之后t行,每行二个整数n,k。含义如题面描述。
k<=n<=10^18,t<=10^5
Output
t行每行一个整数,表示其粒子流的威力之和模2333的值。
Sample Input
1
5 5
5 5
Sample Output
32
HINT
Source
题目大意
给定$n, k$,求$sum_{i = 0} ^{k}C_{n}^{i}$模2333的余数。
显然Lucas。
$sum_{i = 0} ^{k}C_{n}^{i}\ =sum_{i = 0} ^ {k}C_{n \% p}^{i\% p}C_{left lfloor frac{n}{p} ight floor}^{left lfloor frac{i}{p} ight floor}\ =left (sum_{i = 0}^{p}C_{n \% p}^{i\% p} ight )left ( sum_{i = 0}^{left lfloor frac{k}{p} ight floor - 1} C_{left lfloor frac{n}{p} ight floor} ^ {left lfloor frac{i}{p} ight floor} ight ) + C_{left lfloor frac{n}{p} ight floor}^{left lfloor frac{k}{p} ight floor}left ( sum_{i = 0}^{k \% p}C_{n \% p}^{i} ight )$
考虑中间的一步可以进行递归计算。又因为$p = 2333$,所以最后一个前缀和可以预处理。
会出现一个较大的组合数,可以直接用Lucas算。
其实它可先用Lucas预处理,这样可以少个log。
Code
1 /** 2 * bzoj 3 * Problem#4591 4 * Accepted 5 * Time: 4140ms 6 * Memory: 44008k 7 */ 8 #include <bits/stdc++.h> 9 #ifndef WIN32 10 #define Auto "%lld" 11 #else 12 #define Auto "%I64d" 13 #endif 14 using namespace std; 15 typedef bool boolean; 16 #define ll long long 17 18 const int p = 2333; 19 20 ll n, k; 21 22 int pow2[p + 5]; 23 int C[p + 5][p + 5]; 24 int sc[p + 5][p + 5]; 25 26 inline void prepare() { 27 pow2[0] = 1; 28 for (int i = 1; i < p; i++) 29 pow2[i] = (pow2[i - 1] << 1) % p; 30 31 C[0][0] = 1; 32 for (int i = 1; i < p; i++) { 33 C[i][0] = C[i][i] = 1; 34 for (int j = 1; j < i; j++) 35 C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % p; 36 } 37 38 for (int i = 0; i < p; i++) { 39 sc[i][0] = 1; 40 for (int j = 1; j < p; j++) 41 sc[i][j] = (sc[i][j - 1] + C[i][j]) % p; 42 } 43 } 44 45 inline void init() { 46 scanf(Auto""Auto, &n, &k); 47 } 48 49 int Lucas(ll n, ll k) { 50 if (!n && !k) return 1; 51 return Lucas(n / p, k / p) * C[n % p][k % p] % p; 52 } 53 54 int S(ll n, ll k) { 55 if (k < 0) return 0; 56 return (pow2[n % p] * S(n / p, k / p - 1) + Lucas(n / p, k / p) * sc[n % p][k % p]) % p; 57 } 58 59 inline void solve() { 60 printf("%d ", S(n, k)); 61 } 62 63 int T; 64 int main() { 65 prepare(); 66 scanf("%d", &T); 67 while (T--) { 68 init(); 69 solve(); 70 } 71 return 0; 72 }