zoukankan      html  css  js  c++  java
  • 51Nod1802 左偏树计数

    题目大意

    求$n$个点的无标号左偏树个数

    既然你都点进来了,那么估计也是奔着题解来的....

    废话少说....

    首先,左偏树有这么一些性质

    设最右链长度为$r[p]$

    1.左偏树的子树仍然是左偏树

    2. $r[p] = r[rs[p]] + 1$

    3. $r[p] leqslant log_2 (p + 1)$

    因此,考虑设状态$dp[i][j]$表示$i$个点构成右链长度为$j$的方案数

    由于右儿子的右链长度一定为$j - 1$

    只要枚举左儿子右链长度和左儿子子树大小就能转移

    但是这样子复杂度会爆炸

    因此考虑剪枝

    首先,右链长度为$j$代表着其子树大小一定大于等于$2^j - 1$

    然后,左儿子右链长度一定大于等于$j - 1$

    然后就可以AC了

    反正随意调一调发现过了样例然后就一A了.......

    其实还有可以优化的地方,但是人太懒了....

    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    #define sid 1005
    #define ri register int
    
    int n, p;
    int bit[sid], lg2[sid];
    int f[sid][15];
    
    int main() {
        cin >> n >> p;
        for(ri i = 0; i <= 25; i ++) bit[i] = 1 << i;
        for(ri i = 2; i <= n + 1; i ++) lg2[i] = lg2[i >> 1] + 1;
        
        f[0][0] = 1; f[1][1] = 1;
        for(ri i = 2; i <= n; i ++)
        for(ri j = 1; j <= lg2[i + 1]; j ++)
        for(ri lp = j - 1; bit[lp] + bit[j - 1] - 2 <= i; lp ++)
        for(ri L = bit[lp] - 1; ; L ++) {
            if(L > i) break;
            if(i - L - 1 < bit[j - 1] - 1) break;
            f[i][j] = (f[i][j] + 1ll * f[L][lp] * f[i - L - 1][j - 1] % p) % p;
        }
        
        int ans = 0;
        for(ri i = 0; i <= lg2[n + 1]; i ++)
        ans = (ans + f[n][i]) % p;
        printf("%d
    ", ans); 
        return 0;
    }
  • 相关阅读:
    Linux文件权限学习总结
    【转】Hibernate和ibatis的比较
    Spring AOP原理及拦截器
    Spring AOP (下)
    Spring AOP (上)
    SQL语句限定查询知识点总结
    多线程知识点总结
    关于tomcat那些事情
    java.lang.NoClassDefFoundError: org/apache/commons/codec/DecoderException 的解决办法
    cacti 与 nagios 一些总结 【八】
  • 原文地址:https://www.cnblogs.com/reverymoon/p/9471427.html
Copyright © 2011-2022 走看看