题目描述 Description

精灵心目中亘古永恒的能量核心崩溃的那一刻,Bzeroth 大陆的每个精灵都明白,他们的家园已经到了最后的时刻。
就在这危难关头,诸神天降神谕,传下最终兵器——潘少拉魔盒。然而当精灵们准备打开魔盒时,魔盒的守护灵出现在精灵们面前:“如果你们想要拯救世界,必须要先解决这个困难的问题:定义一个 N 阶数列 A 为神奇数列当且仅当对所有2≤i≤N−1 ,都有 Ai−1+Ai+1≥2×Ai。现在有一个N阶正整数列B ,请计算将 B 数列均匀随机打乱之后,得到的数列是神奇数列的概率 P 。你只需要输出P×(N!)mod998244353 的结果即可。(显然 P×(N!) 一定是个整数)。”

输入描述 Input Description

第一行为 1 个正整数 N。
第二行为 N 个正整数 Ai。

输出描述 Output Description

输出 P×(N!)mod998244353 的结果。

样例输入 Sample Input

4
1 2 1 3

样例输出 Sample Output

  1. 8

数据范围及提示 Data Size & Hint

对于 50%的数据:3 ≤ N ≤ 10。
对于 80%的数据:3 ≤ N ≤ 20。
对于 100%的数据:3 ≤ N ≤ 40,1≤Ai≤109 。


容易知道,这个题实际上是想让我们求给定的集合能够拼成多少个神奇数列。

经过推一波式子,我们可以知道a[i+1]-a[i]>=a[i]-a[i-1],所以它的差分序列单调递增,即其为一个下凸函数。。

因此,对于一个神奇数列,满足它一定是一个下凸函数。

考虑在这个函数上进行dp:

对于一个区间dp[i][k],表示区间最左端取值为a[i],最右端取值为a[k],则进行转移时每次往左端或右端放入一个点。

但是由于刚才的式子,我们必须记录端点之前的位置的取值,所以我们用dp[i][j][k][l]表示某个下凸函数的一段区间最左端取值为a[i],a[j],最右端取值为a[l],a[k]的神奇序列个数。

考虑将原来的集合排序,所以易知下凸函数的顶点一定是整个集合的最小值。

由此,我们每次考虑放入一个新值a[pos]满足pos=max(i,k)+1,原因是排好序的序列单调递增,又因为a[i],a[k]一定含有当前区间值最大的点(因为是下凸函数),所以我们只需要取二者下标最大值+1作为新值下标。所以可以用刚才的方法检验是否答案合法。

上代码:

  1. #include<iostream>
  2. #include<algorithm>
  3. #include<cmath>
  4. #include<queue>
  5. #include<cstring>
  6. #include<cstdio>
  7. using namespace std;
  8. typedef long long LL;
  9. #define mem(a,b) memset(a,b,sizeof(a))
  10. typedef pair<int,int> PII;
  11. typedef pair<int,PII> PIP;
  12. const int MOD=,maxn=;
  13. inline int read()
  14. {
  15. int x=,f=;char c=getchar();
  16. while(!isdigit(c)){if(c=='-')f=-;c=getchar();}
  17. while(isdigit(c)){x=x*+c-'';c=getchar();}
  18. return x*f;
  19. }
  20. int n,a[maxn],sum=,jc[maxn],dp[maxn][maxn][maxn][maxn],ans;
  21. int main()
  22. {
  23. n=read();
  24. jc[]=;
  25. for(int i=;i<=n;i++)a[i]=read(),jc[i]=((LL)jc[i-]*(LL)i)%MOD;//阶乘预处理
  26. sort(a+,a+n+);
  27. for(int i=;i<=n;i++)
  28. {
  29. if(a[i]!=a[i-])break;
  30. sum++;
  31. }//取出区间最小值
  32. for(int i=sum+;i<=n;i++)a[i-sum+]=a[i];//把其它最小值扔到后面
  33. dp[][][][]=;
  34. n=n-sum+;//去掉与最小值相同的值
  35. for(int i=;i<=n;i++)
  36. for(int j=;j<i;j++)
  37. for(int k=;k<=n;k++)
  38. for(int l=;l<k;l++)
  39. {
  40. int pos=max(i,k)+;//找到新加入的数
  41. if(pos==n+){ans=(ans+dp[i][j][k][l])%MOD;continue;}//如果整个下凸函数已经构成了长度为n的区间
  42. if(*a[i]<=a[pos]+a[j] || i==)dp[pos][i][k][l]=(dp[pos][i][k][l]+dp[i][j][k][l])%MOD;//检查i端是否合法
  43. if(*a[k]<=a[pos]+a[l] || k==)dp[i][j][pos][k]=(dp[i][j][pos][k]+dp[i][j][k][l])%MOD;//检查k端是否合法
  44. }
  45. printf("%d\n",((LL)ans*(LL)jc[sum])%MOD);//因为最小值一共有sum个取值,所以这sum个取值进行全排列再乘以答案即可
  46. return ;
  47. }

2019.10.24 CSP%你赛第二场d1t3的更多相关文章

  1. 2019.10.26 CSP%您赛第三场

    \(CSP\)凉心模拟^_^ --题源\(lqx.lhc\)等各位蒟蒻 题目名称 比赛 传递消息 开关灯 源文件名 \(competition.cpp\) \(message.cpp\) \(ligh ...

  2. 2019.10.28 CSP%您赛第四场t3

    我写不动前两个了. 原谅一下. ____________________________________________________________________________________ ...

  3. 2019.10.29 CSP%您赛第四场t2

    我太菜了我竟然不会分层图最短路 ____________________________________________________________________________________ ...

  4. Contest1592 - 2018-2019赛季多校联合新生训练赛第二场(部分题解)

    Contest1592 - 2018-2019赛季多校联合新生训练赛第二场 D 10248 修建高楼(模拟优化) H 10252 组装玩具(贪心+二分) D 传送门 题干 题目描述 C 市有一条东西走 ...

  5. NOI.AC NOIP模拟赛 第二场 补记

    NOI.AC NOIP模拟赛 第二场 补记 palindrome 题目大意: 同[CEOI2017]Palindromic Partitions string 同[TC11326]Impossible ...

  6. 可持久化线段树的学习(区间第k大和查询历史版本的数据)(杭电多校赛第二场1011)

    以前我们学习了线段树可以知道,线段树的每一个节点都储存的是一段区间,所以线段树可以做简单的区间查询,更改等简单的操作. 而后面再做有些题目,就可能会碰到一种回退的操作.这里的回退是指回到未做各种操作之 ...

  7. 2019 计蒜之道 初赛 第二场 B. 百度AI小课堂-上升子序列(简单) ( 实现)

    题目背景 ​91029102 年 99 月 22 日,百度在 X 市 XX 中学举办的第一场 AI 知识小课堂大获好评!同学们对矩阵的掌握非常棒. 今天的 AI 知识小课堂的第二场开讲啦.本场 AI ...

  8. 2019杭电多校赛第九场 Rikka with Mista

    Problem Description Rikka is a fervent fan of JoJo's Bizarre Adventure. As the last episode of Golde ...

  9. 2019 HDU 多校赛第二场 HDU 6598 Harmonious Army 构造最小割模型

    题意: 有n个士兵,你可以选择让它成为战士还是法师. 有m对关系,u和v 如果同时为战士那么你可以获得a的权值 如果同时为法师,你可以获得c的权值, 如果一个为战士一个是法师,你可以获得b的权值 问你 ...

随机推荐

  1. 同步FIFO design and IP level verification

    一.前言 应聘IC前端相关岗位时,FIFO是最常考也是最基本的题目.FIFO经常用于数据缓存.位宽转换.异步时钟域处理.随着芯片规模的快速增长,灵活的system verilog成为设计/验证人员的基 ...

  2. Oracle内置函数之数值型函数

    think different

  3. [Leetcode] 第299题 猜数字游戏

    一.题目描述 请写出一个根据秘密数字和朋友的猜测数返回提示的函数,用 A 表示公牛,用 B 表示奶牛. 请注意秘密数字和朋友的猜测数都可能含有重复数字. 示例 1: 输入: secret = &quo ...

  4. Elasticsearch(10) --- 内置分词器、中文分词器

    Elasticsearch(10) --- 内置分词器.中文分词器 这篇博客主要讲:分词器概念.ES内置分词器.ES中文分词器. 一.分词器概念 1.Analysis 和 Analyzer Analy ...

  5. 【linux】【elasticsearch】docker部署elasticsearch及elasticsearch-head

    前言 Elasticsearch是一个基于Apache Lucene(TM)的开源搜索引擎.无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进.性能最好的.功能最全的搜索引擎库.但是,Lu ...

  6. 我对android handle更新UI 的一些理解

    1.handle可以方便快捷地管理子线程对主线程UI 的更新, 2.如果不用handle,当多个子线程同时请求更新UI 时,UI更新操作就无法进行

  7. Hive窗口函数最全案例详解

    语法: 分析函数 over(partition by 列名 order by 列名 rows between 开始位置 and 结束位置) 常用分析函数: 聚合类 avg().sum().max(). ...

  8. Dubbo学习系列之十三(Mycat数据库代理)

    软件界有只猫,不用我说,各位看官肯定知道是哪只,那就是大名鼎鼎的Tomcat,现在又来了一只猫,据说是位东方萌妹子,暂且认作Tom猫的表妹,本来叫OpencloudDB,后又改名为Mycat,或许Ca ...

  9. 基于Docker搭建大数据集群(二)基础组件配置

    主要内容 jdk环境搭建 scala环境搭建 zookeeper部署 mysql部署 前提 docker容器之间能免密钥登录 yum源更换为阿里源 安装包 微云分享 | tar包目录下 JDK 1.8 ...

  10. mysql 时间与字符串相互转换

    时间.字符串.时间戳之间的相互转换:date转字符串.date转时间戳.字符串转date.字符串转时间戳.时间戳转date,时间戳转字符串用法 涉及的函数 date_format(date, form ...