[关闭]
@ZCDHJ 2019-09-17T07:16:15.000000Z 字数 1621 阅读 633

SHOI2015 超能粒子炮·改

Lucas定理


推一下柿子

然后把能预处理的预处理出来,其他的递归计算就行了。

  1. #include <iostream>
  2. #include <cstdio>
  3. typedef long long LL;
  4. #define int LL
  5. const int P = 2333;
  6. int c[2334][2334], f[2334][2334], pow[2334];
  7. inline int read() {
  8. register int x = 0;
  9. register char ch = getchar();
  10. while (!isdigit(ch)) ch = getchar();
  11. while (isdigit(ch)) {
  12. x = x * 10 + ch - '0';
  13. ch = getchar();
  14. }
  15. return x;
  16. }
  17. int C(int n, int k) {
  18. if (n < k) return 0;
  19. if (n <= P) return c[n][k];
  20. return C(n / P, k / P) * c[n % P][k % P] % P;
  21. }
  22. int F(int n, int k) {
  23. if (k < 0) return 0;
  24. if (n <= P) return f[n][std::min(n, k)];
  25. return ((F(n / P, k / P - 1) * pow[n % P]) % P + (C(n / P, k / P) * f[n % P][k % P]) % P) % P;
  26. }
  27. signed main() {
  28. c[0][0] = 1;
  29. for (int i = 1; i <= P; ++i) {
  30. c[i][0] = c[i][i] = 1;
  31. for (int j = 1; j < i; ++j) {
  32. c[i][j] = c[i - 1][j] + c[i - 1][j - 1];
  33. if (c[i][j] >= P) c[i][j] -= P;
  34. }
  35. }
  36. pow[0] = 1;
  37. for (int i = 1; i <= P; ++i) pow[i] = (pow[i - 1] << 1) % P;
  38. for (int i = 0; i <= P; ++i) {
  39. f[i][0] = 1;
  40. for (int j = 1; j <= P; ++j) {
  41. f[i][j] = f[i][j - 1] + c[i][j];
  42. if (f[i][j] >= P) f[i][j] -= P;
  43. }
  44. }
  45. int T = read();
  46. while (T--) {
  47. int n = read(), k = read();
  48. printf("%lld\n", F(n, k));
  49. }
  50. return 0;
  51. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注