• 【HNOI】合唱队


    【HNOI】合唱队

    题意

    对于一个初始序列,保证两两不同,通过一些变换得到目标序列:
    第一个值直接插入空的当前队列
    对于从第二个值开始的每个值
    如果原序列中 $ a[i] $,若 $ a[i]>a[i-1]$ ,那么插入新队列的最右边
    如果原序列中 (a[i]),若 (a[i]<a[i-1]),那么插入新队列的最左边
    给定目标序列,问有多少个初始序列按照上述方式变化后可以得到目标序列
    (1000<=Hi<=2000)(1<=N<=1000)

    解法

    设 $ f[i][j][0/1]$表示第 i~j 区间内的最后一个点是从左边加进来还是从右边加进来,然后就可以转移了。

    注意 : 为了满足无后效性,需要先枚举区间的长度。

    代码如下:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <cctype>
    #define INF 2139062143
    #define MAX 0x7ffffffffffffff
    #define del(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    template<typename T>
    inline void read(T&x)
    {
        x=0;T k=1;char c=getchar();
        while(!isdigit(c)){if(c=='-')k=-1;c=getchar();}
        while(isdigit(c)){x=x*10+c-'0';c=getchar();}x*=k;
    }
    const int maxn=1000+5;
    const int mod=19650827;
    int a[maxn];
    int f[maxn][maxn][2];
    int n;
    int main()
    {
    	read(n);
    	for(int i=1;i<=n;i++) read(a[i]);
    	for(int i=1;i<=n;i++) f[i][i][0]=1;
    	for(int l=2;l<=n;l++){
    		for(int j=l;j<=n;j++){
    			int i=j-l+1;
    			if(a[i]<a[j]) f[i][j][1]+=f[i][j-1][0];
    			if(a[i]<a[j]) f[i][j][0]+=f[i+1][j][1];
    			if(a[i]<a[i+1]) f[i][j][0]+=f[i+1][j][0];
    			if(a[j]>a[j-1]) f[i][j][1]+=f[i][j-1][1];
    			f[i][j][1]%=mod;
    			f[i][j][0]%=mod;
    		}
    	}
    	printf("%d",(f[1][n][0]+f[1][n][1])%mod);
    	return 0;
    }
    
  • 相关阅读:
    Redis学习——(1)Redis安装与配置
    Ubuntu14.04安装Apache2+SVN+Trac
    Ubuntu14.04配置文件Apache2.conf
    Ubuntu系统用户忘记密码
    java中无符号类型的处理[转]
    Golang 切片(slice)扩容机制源码剖析
    无线网络:无线城域网和无线广域网
    vue项目 镜像重置的命令
    批量下载阿里云rpm包
    HttpClient psot和get请求
  • 原文地址:https://www.cnblogs.com/mrasd/p/9520239.html
Copyright © 2020-2023  润新知