首页 > 其他分享 >[题目记录]一本通高手训练-交换

[题目记录]一本通高手训练-交换

时间:2024-12-02 21:10:30浏览次数:4  
标签:高手 排列 题目 int 元素 交换 一本 一个 define

题意

定义操作如下 : 用 \(0\cdots n-1\) 的一个排列 \({q_n}\) 交换排列 \({s_n}\) :

对 \(s_i\) 中的元素进行 \(n-1\) 次两两交换 , 第 \(i\) 次交换 \(s_{q_i}\) 和 \(s_{q_{i+1}}\) .

当 \(s_i=i\) 时 , 求排列 \(q_n\) 的个数 , 使得用 \(q_n\) 交换 \(s_n\) 得到给定的排列 \(p_i\) .

答案对 \(10^9+7\) 取模 .

数据范围 \(n\le 50\) , 来自一本通原题 .

数据范围 \(n\le 10^3\) , \(1s,256MB\) .


题解

显然得到每次交换操作相当于从交换位置断开了整个序列 , 此后无论如何操作 , 左右两边的元素不可能走到另一边 // 这种能够把问题分解的观察常常十分有用

这样 , 如果想要得到目标序列 , 单独看每一个数字的移动过程 , 都要求路径上前一个交换早于后面所有交换进行 , 当且仅当满足这一点能得出目标序列 . 这启发我们类似 CSP-2019 树上的数 一样的拓扑序视角看问题 . 因为每一个数字的移动过程产生的限制都可以用一个链描述 , 即前一个交换早于后一个 , 因此可以在 \(O(n^2)\) 的时间中得出 \(n-1\) 个相邻项交换之间的偏序关系 .

如何考虑计数 , 要求构造的是一个排列 , 而且后面的转移只和当前的最后一个交换的操作时间有关 , 经典地维护排列前 \(i\) 位的相对位置 .

简单描述一下这个 trick

就是说我们要构造一个排列的方案数 , 因为简单地研究每一个元素的排名的状态很大 , 所以转而对前 \(i\) 个元素描述一个 \(1 \cdots i\) 的排列表示这些元素之间的相对位置 , 每次加入新元素就枚举插入每个位置 , 并把后面的元素排名加一 .

这样做的好处是不用再考虑每一个排名是不是已经被前面的元素占据 , 从而可以只记录和转移有关的元素的相对排名 , 从而减少状态 .

对于这道题, 维护 \(f_{i,j}\) 表示前 \(i\) 个元素 , 其中第 \(i\) 个元素的排名是 \(j\) 的状态数 .

每次更新 \(i+1\) , 如果 \(i\) 早于 \(i+1\) :

\[f_{i+1,j}=\sum_{k=1}^{j-1} f_{i,j} \]

如果 \(i\) 晚于 \(i+1\) :

\[f_{i+1,j} = \sum_{k=j}^{i} f_{i,j} \]

如果没有限制关系直接全加一起 :

\[f_{i+1,j} = \sum_{k=1}^{i} f_{i,j} \]

前缀和优化即可 \(O(n^2)\) 完成.

代码
#include<bits/stdc++.h>
#define file(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define int long long
#define INF 0x3f3f3f3f
#define INF64 1e18
using namespace std;

constexpr int N=5e3+5;
constexpr int p=1e9+7;

int a[N],n;

int f[N][N],b[N],s[N][N];

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++) {int x;cin>>x;x++;a[x]=i;}
	int ok=1;
	for(int i=1;i<=n;i++){
		if(a[i]>i){
			for(int j=i;j<a[i]-1;j++){
				if(b[j]==0) b[j]=1;
				if(b[j]==2) ok=0;
			}
		}
		else if(a[i]==i) ok=0;
		else {
			for(int j=a[i];j<i-1;j++){
				if(b[j]==0) b[j]=2;
				if(b[j]==1) ok=0;
			}
		}
	}
	if(!ok) {cout<<0;return 0;}
	f[1][1]=1;
	s[1][1]=1;
	for(int i=2;i<n;i++){
		for(int j=1;j<=i;j++){
			if(b[i-1]==0){
				f[i][j]=s[i-1][i-1];
			}
			if(b[i-1]==1){
				f[i][j]=s[i-1][j-1];
			}
			if(b[i-1]==2){
				f[i][j]=(p+s[i-1][i-1]-s[i-1][j-1])%p;
			}
		}
		for(int j=1;j<=i;j++) s[i][j]=(s[i][j-1]+f[i][j])%p;
	}
	cout<<s[n-1][n-1];

			
		
	
}


标签:高手,排列,题目,int,元素,交换,一本,一个,define
From: https://www.cnblogs.com/youlv/p/18582736

相关文章

  • 使用服务器docker搭建Pwn题目
    一、docker的安装1、安装前先卸载操作系统默认安装的dockersudoapt-getremovedockerdocker-enginedocker.iocontainerdrunc2、安装必要支持sudoaptinstallapt-transport-httpsca-certificatescurlsoftware-properties-commongnupglsb-release3、添加gpgKEY(阿......
  • 这个是哪个题目 spj 来着
    有一个数列\(a_1\sima_n\),如果存在\(l\simr\)使得\(2\midr-l+1\)而且\(a_{l+x}=a_{l+\frac{r-l+1}{2}+x}(0\lex\le\frac{r-l+1}{2})\)(即一个字符串连续出现两次),则\(a\)是平凡的。求问一个数列是不是平凡的。首先如果有相邻相同的,一定是平凡的。而且,一定第一位是相......
  • 长期主义下的一本经济账:卷价格更要卷性能
    「 不做陪跑者,要做支撑者。企业成长的每个关键时刻,在背后默默发力。」 今年以来,云的价格战似乎更猛烈了一些。事实上,云服务降价在规模与创新两重推动力下早就是一种常态。作为云的鼻祖,亚马逊云经常是一年连续降价十几次甚至几十次。这种理性降价,是将规模红利与创新红利释放给......
  • C++三级抽测题目(答案+题目)2
    今天我给大家出一套C++三级考题限时3小时,大家加油!!!题目1:求一个两位数的个位和十位的和说明从键盘读入一个两位的整数n,请求出这个两位整数个位和十位的和是多少?输入格式一个两位的整数n。输出格式一个整数,代表n个位和十位的和。样例输入数据124输出数据16......
  • 博主自留二叉树万字长文—>涵盖名词辨析 + 树的两种表示方法 + 所有特殊二叉树 + 图解
    玩转二叉树(概念+图解+例题代码详解)一、树的概念我们知道在计算机什么是树吗?是二月春风似剪刀吗?哈哈哈哈哈哈显然不是我们看下面这张图,可以观察到树的一些特征1、树的特征(1)树是非线性的数据结构,是递归定义的(连通性)(2)子树之间不能有任何交集(无环性)(3)一颗N......
  • C题目:文件
    题目:从键盘输入一些字符,并逐个把它们送到磁盘上去,直到用户输入一个“#”为止。代码:#include<stdio.h>#include<stdlib.h>voidfile1(){FILE*fp;charch,filename[10];printf("请输入文件名:");scanf("%s",filename);getchar();if((fp=fop......
  • 今年最新最值得选的微信小程序毕业设计选题大全新颖的毕设题目(建议收藏!)
    文章目录前言微信小程序毕业设计题目选题大全为什么选择我更多毕设系统作品演示视频可看这里数据库+源码获取前言......
  • React高阶面试题目(六)
    React的formik库定义:Formik是一个用于在React应用程序中构建和处理表单数据的流行开源库。它提供了许多实用的组件和函数,使在React应用程序中处理表单数据变得更加轻松。优点:自动处理表单状态管理,无需手动编写大量的状态管理逻辑。提供了易于使用的表单验证工具,可以快......
  • [ctf]跟着风二西复现NSSCTF流量题目
    题目参考博客https://blog.csdn.net/zerorzeror/article/details/135737476?spm=1001.2014.3001.550220241130 [GKCTF2021]签到解题过程可以看到流量并不多,看到GET和POST里面有tmpshell 然后追踪HTTP流  可以看到初始的这一段字符,因为字符中字母最大的为f,无其他字......
  • SD WebUI必备插件安装,菜鸟轻松成高手!
    一个刚学AI绘画的小菜鸟怎么快速成为StableDiffusionde的高手?答案就是SD插件,只要学会使用SD的各种插件,帮你写正向和负向提示词,修复人脸/身体/手指,高清放大图片,指定人物pose,图片微调等等都可以轻松搞定,善用插件是成为高手必经之路。目录1插件安装方法2基础插件介绍3......