【51Nod1802】左偏树计数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39972971/article/details/82049621

【题目链接】

【思路要点】

  • d p i , j 表示大小为 i ,根节点距离为 j 的左偏树的个数。
  • 转移时枚举左右子树的大小,以及左子树根节点的距离即可。
  • 时间复杂度 O ( N 2 L o g 2 N ) ,可以用前缀和优化至 O ( N 2 L o g N )

【代码】


#include<bits/stdc++.h>

using namespace std;
const int MAXN = 1005;
const int MAXLOG = 15;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 
template <typename T> void read(T &x) {
  x = 0; int f = 1;
  char c = getchar();
  for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
  for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
  x *= f;
}
template <typename T> void write(T x) {
  if (x < 0) x = -x, putchar('-');
  if (x > 9) write(x / 10);
  putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
  write(x);
  puts("");
}
int n, P, dp[MAXN][MAXLOG];
int main() {
  read(n), read(P);
  dp[0][0] = dp[1][1] = 1;
  for (int i = 2; i <= n; i++)
  for (int j = 1; (1 << j) - 1 <= i; j++) {
      int tmp = 0;
      for (int l = 0, r = i - 1; r >= 0; l++, r--)
      for (int k = j - 1; (1 << k) - 1 <= l; k++)
          tmp = (tmp + 1ll * dp[l][k] * dp[r][j - 1]) % P;
      dp[i][j] = tmp;
  }
  int ans = 0;
  for (int i = 1; (1 << i) - 1 <= n; i++)
      ans = (ans + dp[n][i]) % P;
  writeln(ans);
  return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39972971/article/details/82049621
今日推荐