• hdu 5524


      由于是完全二叉树,所以我们可以预先知道整棵树的形状,因此可以判断根节点的两个子节点哪个是满二叉树,哪个不是满二叉树(必然是一边满,一边不满),对于满的子节点,我们可以直接求出它的不同子树的个数,也就是说我们只要递归搜不满的子节点就行了,这样一来,我们的复杂度就只有logn了。

      当然还要解决相同子树判重的问题(只有满二叉子树才会出现重复),这里我用了vis数组来标记已经计算过的子树(例如vis[i],代表树高为i+1的满二叉树,这里注意标记了树高为i的满二叉树,那么所有树高比i+1小的也都要标记掉)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 
     6 typedef long long LL;
     7 
     8 const int maxn = 111;
     9 
    10 LL _n;
    11 
    12 LL sum[maxn], f[maxn];
    13 int vis[maxn];
    14 LL solve(LL n) {
    15     int po = 0;
    16     for (int i = 62; i >= 0; i--) {
    17         if (sum[i] == n) {
    18             LL tmp = 0;
    19             for (int j = i; j >= 0 && vis[j] == 0; j--) {
    20                 tmp++;
    21                 vis[j] = 1;
    22             }
    23             return tmp;
    24         }
    25         else if (sum[i] < n) {
    26             po = i; break;
    27         }
    28     }
    29     //printf("po:%d
    ", po);
    30     LL ret = 1;
    31     LL res = n - sum[po];
    32     if (res > f[po]) {//搜右边
    33         for (int i = po; i >= 0 && vis[i] == 0; i--) {
    34             ret++;
    35             vis[i] = 1;
    36         }
    37         ret+=solve(n - sum[po]-1);
    38     }
    39     else {//搜左边
    40         for (int i = po-1; i >= 0 && vis[i] == 0; i--) {
    41             ret++;
    42             vis[i] = 1;
    43         }
    44         if(po>=1) ret += solve(n - sum[po - 1] - 1);
    45         else ret += solve(n - 1);
    46     }
    47     return ret;
    48 }
    49 
    50 void get_table() {
    51     f[0] = 1;
    52     for (int i = 1; i < 63; i++) f[i] = f[i - 1] << 1;
    53     sum[0] = 1;
    54     for (int i = 1; i < 63; i++) sum[i] = sum[i - 1] + f[i];
    55 }
    56 
    57 void init() {
    58     memset(vis, 0, sizeof(vis));
    59 }
    60 
    61 int main() {
    62     
    63     get_table();
    64     /*
    65     for (int i = 0; i < 10; i++) printf("%lld ", f[i]);
    66     printf("
    ");
    67     for (int i = 0; i < 10; i++) printf("%lld ", sum[i]);
    68     printf("
    ");
    69     */
    70     while (scanf("%lld", &_n) == 1) {
    71         init();
    72         LL ans = solve(_n);
    73         printf("%lld
    ", ans);
    74     }
    75     return 0;
    76 }
    View Code
  • 相关阅读:
    jieba的使用
    如何用python查看自己的电脑有几个核
    NLTK实现文本切分
    nltk的安装和简单使用
    初识NLP 自然语言处理
    mysql 查询存在A表中而不存在B表中的数据
    mysql 导出数据报错: row must be in range 0-65535
    python3 re模块正则匹配字符串中的时间信息
    Python语法速查: 14. 测试与调优
    Python语法速查: 20. 线程与并发
  • 原文地址:https://www.cnblogs.com/fenice/p/5240666.html
Copyright © 2020-2023  润新知