[CF1699C]The Third Problem
做题时间:2022.7.12
给定一个长度为 的排列 ,其中的数包括 ,求出有多少个排列 满足对于 ,满足:
其中 表示在序列 中未出现的最小非负整数。
第一行一个整数 表示数据组数
每组数据第一行一个整数表示
每组数据第二行 个整数表示
共 行,每行一个整数表示答案
组合数学
一开始没有什么头绪,可以从小开始枚举寻找规律。
定义 表示数字 在 中的下标。考虑0的位置,因为 ,因此 中0的位置也是 (可以发现样例也是如此)
考虑1的位置,假设其在0的右边(可以发现在左边和右边的情况是相似的),即 , ,我们可以发现 中的 1 必定在 与 之间,共有 种选择( 不能选 )
那么对于2而言,当它处在0与1之间的时候, 序列 即为 , ,对应地: ,也就是说2必定在 与 之间,共有 种选择( 及 都不能选 );当它处在0与1之外的时候,序列 即为 或 此时 或 ,2在 中的位置仅能为
然后枚举3,4...懒得写了
到这里我们可以发现规律了,除了0之外,第 个数若在 至 组成的区间中,那么它就有 种选择(如果你看不出来,可以参考其他大佬的思路),若不在,说明只有一种情况。最后把这些情况全部乘在一起即可。
#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 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现