[CF1699C]The Third Problem

做题时间:2022.7.12

给定一个长度为 N(N105) 的排列 ai ,其中的数包括 [0,n1] ,求出有多少个排列 bi 满足对于 l,r,1lrN ,满足:

MEX([al,al+1,,ar])=MEX([bl,bl+1,,br]),

其中 MEX([c1,c2,...,ck]) 表示在序列 [c1,ck] 中未出现的最小非负整数。

第一行一个整数 T 表示数据组数
每组数据第一行一个整数表示 N
每组数据第二行 N 个整数表示 a

T 行,每行一个整数表示答案

组合数学

一开始没有什么头绪,可以从小开始枚举寻找规律。

定义 pi 表示数字 ia 中的下标。考虑0的位置,因为 MEX{ap0}=1 ,因此 b 中0的位置也是 p0 (可以发现样例也是如此)

考虑1的位置,假设其在0的右边(可以发现在左边和右边的情况是相似的),即 p1>p0MEX{ap0ap1}2 ,我们可以发现 b 中的 1 必定在 p0p1之间,共有 (p1p0) 种选择( p0 不能选 )

那么对于2而言,当它处在0与1之间的时候, 序列 a 即为 [021]MEX{ap0ap0}3 ,对应地: MEX{bp0bp1}3 ,也就是说2必定在 p0p1 之间,共有 (p1p01) 种选择( p0p1 都不能选 );当它处在0与1之外的时候,序列 a 即为 [201][012] 此时 MEX{ap2,......,ap0}=1MEX{ap1,......,ap2}=0 ,2在 b 中的位置仅能为 p2

然后枚举3,4...懒得写了

到这里我们可以发现规律了,除了0之外,第 k 个数若在 0k1 组成的区间中,那么它就有 (rlk) 种选择(如果你看不出来,可以参考其他大佬的思路),若不在,说明只有一种情况。最后把这些情况全部乘在一起即可。

#include<cstdio>
#include<iomanip>
using namespace std;
const int N=1e5+50,MOD=1e9+7;
int a[N],pos[N],n,t;
int main()
{
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),pos[a[i]]=i;
int l=pos[0],r=pos[0];
long long ans=1;
for(int i=1;i<n;i++){
if(pos[i]<l) l=pos[i];
else{
if(pos[i]>r) r=pos[i];
else ans*=(long long)(r-l+1-i),ans%=MOD;
}
}
printf("%lld\n",ans%MOD);
}
return 0;
}

本文作者:lxzy

本文链接:https://www.cnblogs.com/Unlimited-Chan/p/16475558.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   lxzy  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.