做这道题,很有感悟,发篇文。

先给数列从小到大排个序。

接下来设 \(f_{i,j}\) 表示前 \(i\) 个数的排列形成 \(j\) 个上坡的方案数。

接下来考虑转移,分为插入第 \(i\) 个数后增加上坡和不增加上坡两种情况。

对于不增加的情况,有三种可能:

  • 第 \(i\) 个数插入在了数列的最前端,有 \(1\) 种方案。
  • 第 \(i\) 个数插入在了一个上坡的中间,因为上坡中较小的那个数字必定小于第 \(i\) 个数,形成一个上坡,较大的那个数字必定小于等于第 \(i\) 个数,不形成上坡,而我们拆散了一个上坡,故没有增加,有 \(j\) 种方案。
  • 第 \(i\) 个数插入在了数值相同的数后面,这个记为 \(same_i\),有 \(same_i\) 种方案。

对于增加的情况,就是减去这三种情况了,不过增加了,就说明原来只有 \(j-1\) 个上坡,这里和上面不太一样。

整理式子,得:

\[f_{i,j} = f_{i-1,j-1} \times (i - j - same_i) + f_{i-1,j} \times (1 + j + same_i)
\]

这样就可以 \(O(n^2)\) 求得了,可以用滚动数组。

#include <bits/stdc++.h>
using namespace std;
long long n, k, a[5005], f[5005], same[5005], sum;
int main() {
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; i++) {
if (a[i] == a[i - 1])
same[i] = same[i - 1] + 1;
}
f[0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = i - same[i]; j >= 1; j--) {
f[j] = f[j - 1] * (i - j - same[i]) % 998244353 + f[j] * (1 + j + same[i]) % 998244353;
f[j] %= 998244353;
}
f[0] = f[0] * (1 + same[i]) % 998244353;
}
cout << f[k] << endl;
}

After Increasing K Times

过了一段时间重新看了一下这道题,发现有几个优化,也顺便介绍一下。

首先,我们发现 \(n\) 很大,但是数值区间很小,所以考虑使用桶排序,因为数字在 \([1,n]\),所以排序复杂度为 \(O(n)\)。

然后,我们发现枚举区间可以缩小,因为我们并不是全都需要,简单用一个图表示:

左边是我们需要的值,右边是不需要的。

那么,有用的状态的区间边界很好推算,是 \([k+n-i+1,k]\),这个优化可以减少接近一半的时间。

以上优化让代码大大提速,获得了洛谷最优解,在 AtCoder 排名第二(截至2022.11.23)。

第一名本人丧心病狂卡常也卡不过,快了 4ms,但是本代码很短,最快代码使用了 IDFT。

#include <stdio.h>
inline int read() {
char c = getchar();
int sum = 0;
while (c < '0' || c > '9') c = getchar();
do {
sum = (sum << 3) + (sum << 1) + c - '0';
c = getchar();
} while (c >= '0' && c <= '9');
return sum ;
}
int n, k,s[5005],b[5005],t=1;
long long f[5005];
int main() {
n=read(),k=read();
for (int i = 1; i <= n; i++)b[read()]++;
for(int i=1;i<=n&&t<=n;i++)
{
if(b[i])b[i]--,t++;
while(b[i])b[i]--,s[t] = s[t - 1] + 1,t++;
}
f[0] = 1;
for (int i = 1; i <= n; i++) {
int r=(k>i-s[i])?(i-s[i]):k,l=(k-n+i-1>1)?(k-n+i-1):1;
for (int j = r; j >= l; j--) {
f[j] = f[j] * (j + s[i] + 1) + f[j - 1] * (i - j - s[i]) ;
f[j] %= 998244353;
}
f[0] = f[0] * (s[i] + 1) % 998244353;
}
printf("%lld\n",f[k]);
return 0;
}

ABC267G Increasing K Times 题解的更多相关文章

  1. OJ2237第k小数题解

    题目描述: 有n个数,请你找出第k小的数. 输入描述: 第一行有2个正整数n,k(n,k<=10^7)第二行有n个非负数ai(ai<=10^5) 输出描述: 输出第k小的数. 输入样例: ...

  2. 9.1练习题5 差k素数对 题解

    题目出处:洛谷 P1348 ,题面略有改编. 题目描述 给你两个数 n 和 k ,请求出所有小于等于 n 的相差为 k 的素数对. 输入格式 两个正整数n,k.1<=k<=n<=10 ...

  3. 排序入门练习题3 谁考了第k名 题解

    题目出处:<信息学奥赛一本通>第二章 上机练习1 题目描述 在一次考试中,每个学生的成绩都不相同,现知道了每个学生的学号和成绩,求考第k名的学生的学号和成绩. 输入格式 输入的第一行包含两 ...

  4. 2018ICPC网络赛(焦作站)K题题解

    一.题目链接 https://nanti.jisuanke.com/t/31720 二.题意 给$N$种船只,第$i$种船的载重量是$V_i$,数量是$2^{C_i}-1$.接下来有$Q$次询问,每次 ...

  5. POJ2104 区间第k小

    题意就是区间第k大…… 题解: 前段时间用主席树搞掉了…… 如今看到划分树,是在想来写一遍,结果18号对着学长的代码调了一上午连样例都没过,好桑心…… 今天在做NOI2010超级钢琴,忽然发现用划分树 ...

  6. Codeforces Round #460 (Div. 2) ABCDE题解

    原文链接http://www.cnblogs.com/zhouzhendong/p/8397685.html 2018-02-01 $A$ 题意概括 你要买$m$斤水果,现在有$n$个超市让你选择. ...

  7. HDU 5977 Garden of Eden(点分治求点对路径颜色数为K)

    Problem Description When God made the first man, he put him on a beautiful garden, the Garden of Ede ...

  8. BUPT2017 wintertraining(15) #2 题解

    这场有点难,QAQ.补了好久(。• ︿•̀。) ,总算能写题解了(つд⊂) A. Beautiful numbers CodeForces - 55D 题意 ​ 求\([l,r](1\le l_i\l ...

  9. Moscow Subregional 2013. 部分题题解 (6/12)

    Moscow Subregional 2013. 比赛连接 http://opentrains.snarknews.info/~ejudge/team.cgi?contest_id=006570 总叙 ...

  10. 【codeforces】【比赛题解】#915 Educational CF Round 36

    虽然最近打了很多场CF,也涨了很多分,但是好久没写CF的题解了. 前几次刚刚紫名的CF,太伤感情了,一下子就掉下来了,不懂你们Div.1. 珂学的那场我只做了第一题……悲伤. 这次的Education ...

随机推荐

  1. js判断页面滚动到底部的时候,可以执行一些操作

    <script type="text/javascript">window.onscroll=function(){ var a = document.document ...

  2. SAN证书(转载)

    日常在周末更新相关容器,更新 potainer 2.6.3 后发现所有远程 docker 节点都无法连接了,看了下日志报错是这样的: background schedule error (endpoi ...

  3. NXOpen遍历工作部件表达式

    //用户代码#include <uf_defs.h>#include <NXOpen/NXException.hxx>#include <NXOpen/Session.h ...

  4. [Mac技巧] 你真的会使用Mac的“聚焦搜索”吗?

    Mac的"聚焦搜索"是对Mac整个磁盘的全局搜索,搜索起来极其便捷,但也常被使用者忽略使用. 以下列出比较常用的几个场景供使用者参考 场景一:文件在哪儿,要立即查看? 1.打开&q ...

  5. MySQL:查询语句 case when then 的用法

    转载网址: https://blog.csdn.net/h123hlll/article/details/122366213

  6. Codeforces Round 857 (Div. 2) A-D

    Codeforces Round 857 (Div. 2) A. Likes 求每回合最大的数列:先全使用正数,每个正数对ans++,再全使用负数,每个负数对ans-- 求每回合最小的数列:方法1(模 ...

  7. 痞子衡嵌入式:盘点国内RISC-V内核MCU厂商(2021年发布产品)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是国内RISC-V内核MCU厂商(2021). 虽然RISC-V风潮已经吹了好几年,但2019年才是其真正进入主流市场的元年,最近国内大量 ...

  8. Dcat admin 多文件上传,七牛云云端上传

    进入官网  Dcat Admin - Php后台开发框架 这里要选择1.x 下面来安装框架 安装完laravel之后,需要修改.env文件,设置数据库链接设置正确 安装 dcat-admin comp ...

  9. SqlServer 高并发的情况下,如何利用锁保证数据的稳定性

    sql的锁机制,是时刻贯彻在每一次的sql事务中的,为了理解更透彻,介绍锁之前,我们得先了解,锁是为了干什么!! 1.数据库异常情况 1.1 先来聊聊数据可能发生个异常状况 1)脏读:读未提交,顾名思 ...

  10. RHEL系列邮箱配置mail.rc和s-nail.rc

    RHEL8 1.首先安装postfix和mailx dnf install postfix mailx -y 2.开启postfix服务开机运行 systemctl enable --now post ...