• P8554 心跳


    题目描述

    赫尔德想对上面的问题进行探究,她想先做一些统计,于是她抽象了这个问题。
    我们对于一个长为 l l l 的数列 p p p,定义函数:

    • f ( p ) f(p) f(p) 表示有多少 1 ≤ i ≤ l 1\le i\le l 1il 满足 p i = max ⁡ j = 1 i p j p_i=\max_{j=1}^i p_j pi=maxj=1ipj(即前缀最大值的个数)。
      现在,给定 n , m n,m n,m,请求出有多少满足以下条件的长为 n n n 的,值域在 [ m , n ] [m,n] [m,n] 数列 a a a
    • 存在一个排列 p p p 使得:令 P i P_i Pi 代表 p p p 去掉 p i p_i pi 后的数列(即 [ p 1 , p 2 , … , p i − 1 , p i + 1 , … , p n ] [p_1,p_2,\dots,p_{i-1},p_{i+1},\dots,p_n] [p1,p2,,pi1,pi+1,,pn]), f ( P i ) = a i f(P_i)=a_i f(Pi)=ai
      答案对 1 0 9 + 7 10^9+7 109+7 取模。

    n , m ≤ 2000 n,m\le2000 n,m2000

    题解

    玄妙双射题
    先考虑 m = 1 m=1 m=1怎么做
    考虑给 a a a序列构造一个双射,我们假设 k k k为原排列的前缀最大值个数(可以证明一个 a a a只会对应一个 k k k,所以不会算重)
    a i < k a_iai<k说明不合法, p i p_i pi不是前缀最大值时, a i = k a_i=k ai=k,当 p i p_i pi时前缀最大值的时, a i ∈ [ k − 1 , n ] a_i\in[k-1,n] ai[k1,n]
    分析一下,一个序列中只有 3 3 3种数,一种是前缀最大值称为红色,一种是删除最靠近它的前缀最大之后会变为前缀最大值称为绿色,一种是无论如何都会变成前缀最大值,称为黄色

    我们考虑让一个合法序列 a a a唯一对应一个颜色序列
    我们用以下操作构造颜色序列
    1.首先找到 a i ≠ k a_i\not =k ai=k i i i,把该位置染成红色,在它后面需要 a i − k a_i-k aik个绿色,由于它们相对位置并不重要,所以我们钦定后面的绿色紧跟在红色后面,即 j ∈ [ i + 1 , i + a i − k ] j\in[i+1,i+a_i-k] j[i+1,i+aik]的位置会被染成绿色
    2.假设我们已经钦定了 w w w个位置为红色,显然我们还需要钦定 k − w k-w kw个红色位置,我们每次找出最小的 i i i,使得 a i = a i + 1 = k a_i=a_{i+1}=k ai=ai+1=k,并且 i i i i + 1 i+1 i+1均未被染色,然后把 i i i染红, i + 1 i+1 i+1染绿,不断进行这个操作 k − w k-w kw
    3.其余未染色位值均染成黄色

    显然一个合法的 a a a必定能够对应一个颜色序列,然后一个颜色序列必定能够回推出一个 a a a序列,所以合法 a a a序列和颜色序列构成双射,且显然对于任意一个颜色序列,我们都可以构造出一个合法的 p p p,可以考虑插入构造,所以颜色序列的个数就是合法 a a a的个数

    直接对颜色序列进行计数
    对于颜色序列还有一些隐性限制
    1.第一个一定是红,第二个不能为黄
    2.x为不为绿的颜色,红绿x前不能出现黄黄,不能出现黄红绿,否则不符合构造颜色序列时的操作2
    3.绿紧跟红
    根据这三个限制就可以设计状态了,下面是我自己设计的状态

    0 黄 无黄黄
    1 黄红 无黄黄
    2 黄红绿 无黄黄
    3 绿 无黄黄 前方不是黄红
    4 红 无黄黄 前方非黄
    5 黄 有黄黄
    6 红 有黄黄
    7 红绿 有黄黄
    8 绿绿 有黄黄
    
    

    每行的第二段字表示当前结尾的情况
    m > 1 m>1 m>1的情况就要多记两个东西
    1.红色的个数
    2.是否有红色后面不接绿色
    细节挺多

    code \text{code} code

    #include
    #include
    #define ll long long
    using namespace std;
    const int N=2e3+10,mod=1e9+7;
    int n,m;
    int f[2][9][N+10][N+10];
    void Add(int &a,int b){a+=b;if(a>=mod) a-=mod;}
    int main()
    {
    	scanf("%d %d",&n,&m);
    	n++;
    	f[0][3][1][2]=1;
    	f[1][4][2][2]=1;
    	for(int i=3;i<=n;i++)
    		for(int j=1;j<=n;j++)
    		{
    			for(int k=0;k<=1;k++)
    			{
    				Add(f[k][0][j][i],f[k][1][j][i-1]),Add(f[k][0][j][i],f[k][3][j][i-1]),Add(f[k][0][j][i],f[k][4][j][i-1]);
    				Add(f[k][1][j][i],f[k][0][j-1][i-1]);
    				Add(f[k][2][j][i],f[k][1][j][i-1]);
    				Add(f[k][3][j][i],f[k][2][j][i-1]),Add(f[k][3][j][i],f[k][3][j][i-1]),Add(f[k][3][j][i],f[k][4][j][i-1]);
    				Add(f[k][4][j][i],f[k][1][j-1][i-1]),Add(f[k][4][j][i],f[k][3][j-1][i-1]),Add(f[k][4][j][i],f[k][4][j-1][i-1]);
    				Add(f[k][5][j][i],f[k][0][j][i-1]),Add(f[k][5][j][i],f[k][5][j][i-1]),
    				Add(f[k][5][j][i],f[k][6][j][i-1]),Add(f[k][5][j][i],f[k][8][j][i-1]);
    				Add(f[k][6][j][i],f[k][5][j-1][i-1]),Add(f[k][6][j][i],f[k][6][j-1][i-1]),Add(f[k][6][j][i],f[k][8][j-1][i-1]);
    				Add(f[k][7][j][i],f[k][6][j][i-1]);
    				Add(f[k][8][j][i],f[k][7][j][i-1]),Add(f[k][8][j][i],f[k][8][j][i-1]);
    			}
    			Add(f[1][0][j][i],f[0][1][j][i-1]),Add(f[1][0][j][i],f[0][4][j][i-1]);
    			Add(f[1][4][j][i],f[0][4][j-1][i-1]),Add(f[1][4][j][i],f[0][1][j-1][i-1]);
    			Add(f[1][5][j][i],f[0][6][j][i-1]),Add(f[1][6][j][i],f[0][6][j-1][i-1]);
    
    			Add(f[0][0][j][i],mod-f[0][1][j][i-1]),Add(f[0][0][j][i],mod-f[0][4][j][i-1]);
    			Add(f[0][4][j][i],mod-f[0][4][j-1][i-1]),Add(f[0][4][j][i],mod-f[0][1][j-1][i-1]);
    			Add(f[0][5][j][i],mod-f[0][6][j][i-1]),Add(f[0][6][j][i],mod-f[0][6][j-1][i-1]);
    		}
    	int ans=0;
    	for(int j=m+1;j<=n;j++)
    		for(int k=0;k<=1;k++)
    			Add(ans,f[k][0][j][n]),Add(ans,f[k][5][j][n]);
    	Add(ans,f[0][0][m][n]),Add(ans,f[0][5][m][n]);
    	printf("%lld\n",ans);
    	return 0;
    }
    
  • 相关阅读:
    SpringBoot+Vue+Element-UI实现人事管理系统
    Rust中Option、Result的map和and_then的区别
    两年Java开发工作经验面试总结
    手写RPC框架之泛化调用
    Linux线程编程
    Java运算符
    一键打包,随时运行,Python3项目虚拟环境一键整合包的制作(Venv)
    [Unity好插件之PlayMaker]PlayMaker如何扩展额外创建更多的脚本
    react创建项目后运行npm run eject无法暴露配置文件(已解决!!!)
    华为ACL实验
  • 原文地址:https://blog.csdn.net/Z_Y_S_/article/details/127097614