zoukankan      html  css  js  c++  java
  • bzoj 4824: [Cqoi2017]老C的键盘

    Description

    老 C 是个程序员。    
    作为一个优秀的程序员,老 C 拥有一个别具一格的键盘,据说这样可以大幅提升写程序的速度,还能让写出来的程序
    在某种神奇力量的驱使之下跑得非常快。小 Q 也是一个程序员。有一天他悄悄潜入了老 C 的家中,想要看看这个
    键盘究竟有何妙处。他发现,这个键盘共有n个按键,这n个按键虽然整齐的排成一列,但是每个键的高度却互不相同
    。聪明的小 Q 马上将每个键的高度用 1 ~ n 的整数表示了出来,得到一个 1 ~ n 的排列 h1, h2,..., hn 。为了
    回去之后可以仿造一个新键盘(新键盘每个键的高度也是一个 1 ~ n 的排列),又不要和老 C 的键盘完全一样,小 Q
     决定记录下若干对按键的高度关系。作为一个程序员,小 Q 当然不会随便选几对就记下来,而是选了非常有规律的
    一些按键对:对于 i =2,3, ... , n,小 Q 都记录下了一个字符<或者>,表示 h_[i/2] < h_i 或者h _[i/2] > h_i 
    。于是,小 Q 得到了一个长度为n ? 1的字符串,开开心心的回家了。现在,小 Q 想知道满足他所记录的高度关系的
    键盘有多少个。虽然小 Q 不希望自己的键盘和老 C 的完全相同,但是完全相同也算一个满足要求的键盘。答案可
    能很大,你只需要告诉小 Q 答案 mod 1,000,000,007 之后的结果即可。
     

    Input

    输入共 1 行,包含一个正整数 n 和一个长度为 n ? 1 的只包含<和>的字符串,分别表示键
    盘上按键的数量,和小 Q 记录的信息,整数和字符串之间有一个空格间隔。
     

    Output

    输出共 1 行,包含一个整数,表示答案 mod 1,000,000,007后的结果。    

    Sample Input

    5 <>><

    Sample Output

    3
    共5个按键,第1个按键比第2个按键矮,第1个按键比第3个按键高,第2个按键比第4个
    按键高,第2个按键比第5个按键矮。
    这5个按键的高度排列可以是 2,4,1,3,5 , 3,4,1,2,5 , 3,4,2,1,5 。

    HINT

    Source

    之前看到这个题的时候毫无想法,现在看起来和实验比较的做法差不多(这个题好像有原题,bzoj 2111 和 bzoj 3167)

    woc这原来都是一个题,但是这题我的做法和实验比较的做法差不多;

    首先题目给了一棵完全二叉树,然后给了父亲和儿子的关系,那么我们设dp[i][j],表示i的子树内,i的排名为j的方案数;

    然后做法流程和实验比较类似,合并(x,i),(y,j)时首先分情况枚举合并后x的rank为k;

    1.x>y;

    那么k从i枚举到i+j-1,然后就相当于这样一个问题:

    前半段有k-1个盒子,i-1个红球,k-1-(i-1)个蓝球,后半段有size[x]+size[y]-k个盒子,有size[x]-i个红球,...个蓝球,

    红蓝球都有顺序;

    然后问每个盒子都填了一个球,而且红蓝球的内部顺序不变的方案数:

    那么转移就是:

    2.x<y

    k就是从i+j,枚举到i+size[y],然后转移是一模一样的;

    然后具体实现方法和实验比较一样。。。

    //MADE BY QT666
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int N=1050;
    const int Mod=1e9+7;
    ll c[N][N],size[N],dp[N][N],g[N],head[N],to[N],nxt[N],type[N],cnt,n;
    char s[N];
    void lnk(int x,int y,int z){
        to[++cnt]=y,nxt[cnt]=head[x],type[cnt]=z,head[x]=cnt;
    }
    void dfs(int x){
        size[x]=1;
        for(int p=head[x];p;p=nxt[p]){
    	int y=to[p],flg=type[p];dfs(y);
    	if(flg==1){
    	    if(size[x]==1){
    		for(int i=1;i<=size[y];i++){
    		    for(int j=1;j<=i;j++) (dp[x][j]+=dp[y][i])%=Mod;
    		}
    		size[x]+=size[y];
    		for(int i=1;i<=size[x];i++) g[i]=dp[x][i];
    	    }
    	    else{
    		int tot=size[x]+size[y];
    		for(int i=1;i<=size[x];i++){
    		    for(int j=1;j<=size[y];j++){
    			for(int k=i;k<=i+j-1;k++){
    			    (g[k]+=dp[x][i]*dp[y][j]%Mod*c[k-1][i-1]%Mod*c[tot-k][size[x]-i]%Mod)%=Mod;
    			}
    		    }
    		}
    		size[x]+=size[y];
    		for(int i=1;i<=size[x];i++) dp[x][i]=g[i];
    	    }
    	}
    	else {
    	    if(size[x]==1){
    		for(int i=1;i<=size[y];i++){
    		    for(int j=i;j<=size[y];j++) (dp[x][j+1]+=dp[y][i])%=Mod;
    		}
    		size[x]+=size[y];
    		for(int i=1;i<=size[x];i++) g[i]=dp[x][i];
    	    }
    	    else{
    		int tot=size[x]+size[y];
    		for(int i=1;i<=size[x];i++){
    		    for(int j=1;j<=size[y];j++){
    			for(int k=i+j;k<=i+size[y];k++){
    			    (g[k]+=dp[x][i]*dp[y][j]%Mod*c[k-1][i-1]%Mod*c[tot-k][size[x]-i]%Mod)%=Mod;
    			}
    		    }
    		}
    		size[x]+=size[y];
    		for(int i=1;i<=size[x];i++) dp[x][i]=g[i]; 
    	    }
    	}
        }
        if(size[x]==1) dp[x][1]=1;
        memset(g,0,sizeof(g));
    }
    int main(){
        scanf("%lld",&n);scanf("%s",s+1);
        for(int i=2;i<=n;i++){
    	if(s[i-1]=='<') lnk(i/2,i,1);
    	if(s[i-1]=='>') lnk(i/2,i,2);
        }
        for(int i=0;i<=n;++i) c[i][0]=1;
        for(int i=1;i<=n;++i)
    	for(int j=1;j<=i;++j){
    	    c[i][j]=(c[i-1][j-1]+c[i-1][j])%Mod;
    	}
        dfs(1);ll ans=0;
        for(int i=1;i<=size[1];i++) (ans+=dp[1][i])%=Mod;
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    SDU暑期集训排位(8)
    hdu1423 最长公共上升子序列
    poj2385 Apple Catching (线性dp)
    hdu5857 Median(模拟)
    hdu5858 Hard problem(求两圆相交面积)
    shuoj 1 + 2 = 3? (二分+数位dp)
    Codeforces Round #460 (Div. 2) B Perfect Number(二分+数位dp)
    hdu4734 F(x)(数位dp)
    hdu3709 Balanced Number (数位dp)
    hdu3652 B-number(数位dp)
  • 原文地址:https://www.cnblogs.com/qt666/p/7496400.html
Copyright © 2011-2022 走看看