zoukankan      html  css  js  c++  java
  • NOIP 模拟 $53; m 计数$

    题解 (by;zjvarphi)

    首先考虑几个性质,对于一棵二叉树,其实它的前序遍历就是它的 (dfs) 序,那么:

    1. 这棵树的每棵子树都是连续的一段。
    2. 这颗左子树的节点编号都小于右子树
    3. 这棵树任意一个有左子节点的节点的左子节点编号必定为该节点编号 (+1)

    那么不妨设 (a<b),分两种情况:

    1. (A_a<A_b),那么这种情况就要求 (b) 不在 (a) 的左子树中,体现到 (dfs) 序上就是 (a) 的左子树的一段序列不包括 (b),即 (a) 的左子树大小最大为 (b-a-1)
    2. (A_a>A_b),这种情况只可能是 (b)(a) 的左子树中,体现到 (dfs) 序上就是 (a) 的左子树的一段序列包括 (b),即 (a) 的左子树大小最小为 (b-a)

    这样就可以在最开始的时候把所有节点的左子树大小限制求出来,然后转移:设 (dp_{i,j}) 表示以 (i) 为根,子树大小为 (j) 的合法方案数

    [dp_{i,j}=sum_{k=min_i}^{max_i}dp_{i+1,k}*dp_{i+k+1,j-k-1} ]

    其中 (min_i,max_i) 分别表示 (i) 节点左子树的最小和最大极限值。

    复杂度 (mathcal{O m(Tn^3)})

    Code
    #include<bits/stdc++.h>
    #define Re register
    #define ri Re signed
    #define pd(i) ++i
    #define bq(i) --i
    namespace IO{
        char buf[1<<21],*p1=buf,*p2=buf;
        #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?(-1):*p1++
        struct nanfeng_stream{
            template<typename T>inline nanfeng_stream &operator>>(T &x) {
                Re bool f=false;x=0;Re char ch=gc();
                while(!isdigit(ch)) f|=ch=='-',ch=gc();
                while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=gc();
                return x=f?-x:x,*this;
            }
        }cin;
    }
    using IO::cin;
    namespace nanfeng{
        #define FI FILE *IN
        #define FO FILE *OUT
        template<typename T>inline T cmax(T x,T y) {return x>y?x:y;}
        template<typename T>inline T cmin(T x,T y) {return x>y?y:x;}
        using ll=long long;
        static const int N=440,MOD=1e9+7;
        int lm[2][N],T,n,m;
        ll dp[N][N];
        inline int main() {
            FI=freopen("count.in","r",stdin);
            FO=freopen("count.out","w",stdout);
            cin >> T;
            for (ri z(1);z<=T;pd(z)) {
                cin >> n >> m;
                memset(lm[1],0x3f,sizeof(int)*(n+1));
                memset(lm[0],0,sizeof(int)*(n+1));
                for (ri i(1),a,b;i<=m;pd(i)) {
                    cin >> a >> b;
                    if (a>b) {
                        std::swap(a,b);
                        lm[0][a]=cmax(lm[0][a],b-a);
                    } else lm[1][a]=cmin(lm[1][a],b-a-1);   
                }
                bool fg=false;
                for (ri i(1);i<=n;pd(i)) if (lm[0][i]>lm[1][i]) {fg=true;break;}
                if (fg) {printf("0
    ");continue;} 
                memset(dp,0,sizeof(dp));
                auto MD=[](ll x) {return x>=MOD?x-MOD:x;};
                for (ri i(n);i;bq(i)) {
                    if (!lm[0][i]) dp[i][1]=1;
                    for (ri j(lm[0][i]+1);j<=n-i+1;pd(j)) {
                        int mk=cmin(lm[1][i],j-1);
                        for (ri k(lm[0][i]);k<=mk;pd(k)) dp[i][j]=MD(dp[i][j]+dp[i+1][k]*dp[i+k+1][j-1-k]%MOD);
                        if (mk==j-1) dp[i][j]=MD(dp[i][j]+dp[i+1][j-1]);
                        if (!lm[0][i]) dp[i][j]=MD(dp[i][j]+dp[i+1][j-1]);
                    }
                }
                printf("%lld
    ",dp[1][n]); 
            }
            return 0;
        }
    }
    int main() {return nanfeng::main();}
    
  • 相关阅读:
    print(end=" ") 滚动输出到屏幕
    写入到csv文件的两种方式(pd.DaaFrame 和 csv.writerow)
    pytorch 损失函数(nn.BCELoss 和 nn.CrossEntropyLoss)(思考多标签分类问题)
    pytorch实战(二)hw2——预测收入是否高于50000,分类问题
    信用卡新颖的攻击方式,黑客可非接触式卡进行交易
    微软结束对SolarWinds黑客的内部调查
    Apple M1芯片首款恶意软件曝光
    新的Office恶意软件,黑客可远程窃取信息
    如何审核Active Directory中的密码更改
    特斯拉恶意软件使用新的传送和规避技术
  • 原文地址:https://www.cnblogs.com/nanfeng-blog/p/15270673.html
Copyright © 2011-2022 走看看