经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
BZOJ2655: calc(dp 拉格朗日插值)
来源:cnblogs  作者:自为风月马前卒  时间:2018/12/5 9:54:47  对本文有异议

题意

题目链接

Sol

首先不难想到一个dp

\(f[i][j]\)表示选了\(i\)严格递增的数最大的数为\(j\)的方案数

转移的时候判断一下最后一个位置是否是\(j\)

\[f[i][j] = f[i][j - 1] + f[i - 1][j - 1] * j\]

  1. for(int i = 0; i <= A; i++) f[0][i] = 1;
  2. for(int i = 1; i <= N; i++)
  3. for(int j = 1; j <= A; j++)
  4. f[i][j] = add(f[i][j - 1], mul(f[i - 1][j - 1], j));
  5. cout << mul(f[N][A], fac[N]);

发现还是不好搞,把转移拆开

\(f[i][j] = \sum_{k = 0}^{j - 1} f[i - 1][k] * (k + 1)\)

这个转移就非常有意思了

我们如果把\(i\)看成列,\(k\)看成行,那么转移的时候实际上就是先对第\(k\)行乘上一个系数\(k\),然后再求和

如果我们把第\(i - 1\)列看成一个\(t\)次多项式,显然第\(i\)列是一个\(t+2\)次多项式(求和算一次,乘系数算一次)

这样的话第\(i\)列就是一个最高\(2i+1\)次多项式

插一插就好了

  1. // luogu-judger-enable-o2
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. const int MAXN = 10001;
  5. int A, N, Lim, mod, f[501][MAXN], fac[MAXN], y[MAXN];
  6. int add(int x, int y) {
  7. if(x + y < 0) return x + y + mod;
  8. return x + y >= mod ? x + y - mod : x + y;
  9. }
  10. void add2(int &x, int y) {
  11. if(x + y < 0) x = (x + y + mod);
  12. else x = (x + y >= mod ? x + y - mod : x + y);
  13. }
  14. int mul(int x, int y) {
  15. return 1ll * x * y % mod;
  16. }
  17. int fp(int a, int p) {
  18. int base = 1;
  19. while(p) {
  20. if(p & 1) base = mul(base, a);
  21. a = mul(a, a); p >>= 1;
  22. }
  23. return base;
  24. }
  25. int Large(int *y, int k) {
  26. static int x[MAXN], ans = 0;
  27. for(int i = 1; i <= Lim; i++) x[i] = i;
  28. for(int i = 0; i <= Lim; i++) {
  29. int up = y[i], down = 1;
  30. for(int j = 0; j <= Lim; j++) {
  31. if(i == j) continue;
  32. up = mul(up, add(k, -x[j]));
  33. down = mul(down, add(x[i], -x[j]));
  34. }
  35. add2(ans, mul(up, fp(down, mod - 2)));
  36. }
  37. return ans;
  38. }
  39. int main() {
  40. #ifndef ONLINE_JUDGE
  41. freopen("a.in", "r", stdin);
  42. // freopen("a.out", "w", stdout);
  43. #endif
  44. cin >> A >> N >> mod; Lim = 2 * N + 1;
  45. fac[0] = 1; for(int i = 1; i <= N; i++) fac[i] = mul(i, fac[i - 1]);
  46. for(int i = 0; i <= Lim; i++) f[0][i] = 1;
  47. for(int i = 1; i <= N; i++) {
  48. for(int j = 1; j <= Lim; j++) {
  49. f[i][j] = add(f[i][j - 1], mul(f[i - 1][j - 1], j));
  50. }
  51. }
  52. for(int i = 0; i <= Lim; i++) y[i] = f[N][i];
  53. cout << mul(Large(y, A), fac[N]);
  54. return 0;
  55. }
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号