首页 > 其他分享 >CSP-J 模拟赛 C 题讲解

CSP-J 模拟赛 C 题讲解

时间:2023-08-20 22:44:29浏览次数:38  
标签:数列 int long times 插入 模拟 讲解 CSP dp

前言

鸣谢:感谢 LHT 大佬的推荐、GCK 大佬的提醒以及 LBJ 大佬帮我接龙。

原题链接

随手给大家扔一份吧。

题目大意

给你一个 \(1\) 到 \(n\) 的数列,当 \(a_i < a_{i-1}\) 的时候(大于号和小于号其实不用管,因为最后所有方案都会遍历到,对答案没有影响)放置一个红色灯笼,否则放置一个绿色灯笼。问正好放置 \(k\) 个红灯笼的排列方式有几种。由于答案很大,所以将答案对 \(2012\) 取模。

简化题意:
对于 \(1\) 到 \(n\) 的所有排列,在其中插入不等号,其中恰好有 \(k\) 个小于号的方案数。

No.1 30pts 暴力

思路

既然是询问有几个满足要求的排列,我们就可以用 next_permutation 枚举全排列,记录下答案数。

代码

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;

int n,k,ans;
int a[1000006];

signed main(){
	cin>>n>>k;
	for(int i=1;i<=n;i++)a[i]=i;

	do{
		int cnt=0;
		for(int i=2;i<=n;i++)
			if(a[i-1]<a[i])cnt++;//注意是插入小于号的方案数(其实改成大于号也不会有影响
		if(cnt==k)ans++;//k 个红灯笼
		ans%=2012;//取模
	}while(next_permutation(a+1,a+n+1));//枚举全排列
	
	cout<<ans<<endl;
	return 0;
}

No.2 100pts 正解

思路

动态规划 DP。

维护一个数组 \(dp\),\(dp_{i,j}\) 代表前 \(i\) 个数字构成的数列中 \(<\) 有 \(j\) 个的方案数。那么 \(>\) 就有 \(i-j-1\) 个,为什么要 \(-1\) 呢?因为 \(i\) 个数的数列中一共只有 \(i-1\) 个间隔,也就是有 \(i-1\) 个不等号(这类似于小学的种树问题,想必大家是可以理解的),那么 \(i-1\) 个不等号中有 \(j\) 个 \(<\),自然 \(>\) 的数量就是剩下的 \(i-1-j\) 个了。

既然是用到 DP 了,那么我们换一种方法来理解此题:“把数字从小到大插入到数列中”。

按照上述的理解,我们接下来再来考虑一下转移的方程式:

我们可以发现,数 \(i\) 插入的位置无非有两种情况:插在原来是 \(<\) 的位置或插在原来是 \(>\) 的位置。
举个栗子:

image

在这幅图中,绿色的属于第一种情况:插在原来是 \(<\) 的位置上,而蓝色就对应的属于第二种情况:插在原来是 \(>\) 的位置上。

接下来我们来分情况讨论:

  1. 插在 \(<\) 的位置上:

image

如图所示,我们对比原先的数列可以发现,该种放置方式会使 \(<\) 的数量不变,\(>\) 的数量增加一。(这里注意,插入的数一定是当前数列中最大的,因为我们是按照从小到大的顺序插入数字的)。

  1. 插在 \(>\) 的位置上:

image

同样如图所示,对比原先数列发现,此种放置方式会使 \(>\) 的数量不变,\(<\) 的数量加一。

分类讨论之后,综上所述,我们就可以得到了转移方程式:

\(dp_{i,j} = dp_{i-1,j-1} \times (i-j-1) + dp_{i-1,j} \times (j)\)

But......

这个转移方程真的正确吗?

乍一看确实没毛病对吧,每次的方案数都等于 放在大于号位置的方案数 + 放在小于号位置的方案数。但是我们考虑,难道插入的这个数字只能放在两个数之间吗?

答案是 false 的,插入的数还可以放到整个数列的最左端或最右端,like:

image

所以说,可以插入的位置不仅仅是这个数列中的一个位置,也可以放在这个数列的边缘,所以最终的转移方程式其实是:

\(dp_{i,j} = dp_{i-1,j-1} \times (i-j) + dp_{i-1,j} \times (j+1)\)(即将 \(>\) 和 \(<\) 的可以插入的位置分别 \(+1\))。

代码

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int mod=2012;

int n,k,dp[1005][1005];

signed main(){
	cin>>n>>k;
	for(int i=1;i<=n;i++)dp[i][0]=1;//注意要赋初值
	
	for(int i=2;i<=n;i++)
		for(int j=1;j<=n;j++)
			dp[i][j]=(dp[i-1][j-1]*(i-j)+dp[i-1][j]*(j+1))%mod;//转移方程式
			
	cout<<dp[n][k]<<endl;//n 个数 k 个小于号
	return 0;
}

标签:数列,int,long,times,插入,模拟,讲解,CSP,dp
From: https://www.cnblogs.com/CheZiHe929/p/17644784.html

相关文章

  • java脚本模拟服务器内存溢出实战&服务器部署java项目
    一、背景:使用javaspringboot,实现linux服务器内存溢出情况。二、方案1、打包成war包,可以直接将war包部署在tomcat容器里2、springboot,打包成jar包。打的jar包,内置了tomcat,所以在服务器上,直接启jar包就行,没有必要放在tomcat容器里部署,在启动jar包时,可以配置线程池等。这......
  • 模拟实现简单的list
    这篇博客主要是关于使用模板实现list的模拟。什么是list:list是一种序列式容器,可以在常数时间内在任意位置进行插入和删除操作,并且支持前后双向迭代。list的底层是双向链表结构,每个元素存储在独立的节点中,节点通过指针指向前一个元素和后一个元素。list与forward_list非常相似,最主......
  • NOIP模拟2总结
    NOIP模拟2总结目录NOIP模拟2总结整体上:个体上第一题:zerosEGOI2021day1t1第二题:lunaEGOI2021day1t2第三题:cowsEGOI2021day2t3第四题:lanternsEGOI整体上:T1非常简单,但是在简单的T2耗费了大量的时间用于证明,导致简单的T3题都没看就跳过,T4暴力没得分个体上第一题:zero......
  • java基础类讲解
    一、Calendar类packagecom.qf.chapter_01;importjava.util.Calendar;publicclassTestCalendar{ publicstaticvoidmain(String[]args){ //创建Calendar对象 Calendarcalendar=Calendar.getInstance();//得到当前时间 System.out.println(calendar.getTime().......
  • 超实用的 linux atop 与 htop 监控工具讲解与实战操作
    目录一、概述1)atop概2)htop概述二、top,atop和htop对比1)top2)atop3)htop三、atop与htop监控工具安装四、atop与htop命令的基本语法1)atop2)htop一、概述atop和htop都是Linux系统上用于监控系统资源和进程活动的命令行工具,但它们有不同的特点和用途。atop实时监控示......
  • Streamlit 讲解专栏(七):解析数据元素
    1前言欢迎来到我的博客!......
  • CSP模拟26
    可做场,拜谢fengwu老师。A.Reversi(AGC031B)题目链接一眼切了设$dp_i$表示考虑到第$i$个石头的总方案数。可由两种情况转移,不选择染色和选择染色,不染色直接由$dp_{i-1}$转移过来,染色由上一个和当前颜色相同的的石头转移过来,相当于把两个石子之间的染色。因为一......
  • Streamlit 讲解专栏(八):图像、音频与视频魔法
    1前言欢迎各位读者来到“最全Streamlit教程”专栏系列!如果您正在寻找一种简单而强大的方式来创建交互式数据应用程序,那么Streamlit无疑是您的最佳选择。作为该领域的热门框架,Streamlit让数据科学家、开发者和爱好者能够以前所未有的速度构建出引人入胜的数据可视化工具。专栏名......
  • CSP模拟赛题解
    目录CSP模拟16T1:糖果CSP模拟17T1:弹珠游戏T2:晚会CSP模拟18T1:TheThirdLetterT2:InaoftheMountainCSP模拟19T1:StrangeFunctionT2:DZYLovesModificationCSP模拟21T1:[CEOI2016]kangarooT2:[JOI2023Final]Advertisement2T3:YourCSP模拟22T1:TheChildandToyCSP模拟16T1:......
  • FEMU模拟器学习笔记
     QEMU参数解析  QEMU的main函数进来后,首先要进行参数解析。一个启动模拟器的命令行如下:x86_64-softmmu/qemu-system-x86_64-name"FEMU-ZNSSD-VM"-enable-kvm-cpuhost-smp2-m4G-devicevirtio-scsi-pci,id=scsi0-devicescsi-hd,drive=hd0-drivefile=/home......