JZOJ7月18日提高组T3 Ocd


毒瘤出题人不说不存在输出“-1”,而且还有40%

题目

点这里,看题目

题解

题意

给出一个 K K K P P P和被重新定义了的字典序
求出在逆序对个数 K K K的情况下,“字典序”第 P P P小的排列

分析

可以设 F [ i ] [ j ] F[i][j] F[i][j]表示前 i i i个位置逆序对个数 j j j的方案数
那么转移显而易见: F [ i ] [ j ] = ∑ j − i + 1 − > j i − 1 F[i][j]=∑_{j-i+1->j}^{i-1} F[i][j]=ji+1>ji1
可知,这个转移的时间复杂度是 O ( N 2 K ) O(N^2K) O(N2K)
由于 N ≤ 1000 , K ≤ 1 0 4 N≤1000,K≤10^4 N1000K104,很明显这个转移会TLE
那么思考优化
我们知道,当 F [ i ] [ j ] > P F[i][j]>P F[i][j]>P时,它对答案是没有任何贡献的
考虑设 B [ i ] [ j ] B[i][j] B[i][j],记录 F [ i ] [ j ] F[i][j] F[i][j] P P P的关系
F [ i ] [ j ] > P F[i][j]>P F[i][j]>P时,我们不需要考虑它
亦或者,当我们在计算 F [ i ] [ j ] F[i][j] F[i][j]时,如果有一个 F [ i − 1 ] [ k ] F[i-1][k] F[i1][k]是大于 P P P的,那么 F [ i ] [ j ] F[i][j] F[i][j]势必会大于 P P P
又比如说:在计算 F [ i ] [ j ] F[i][j] F[i][j]的过程中,加完某个数后 F [ i ] [ j ] > P F[i][j]>P F[i][j]>P,那么 B [ i ] [ j ] B[i][j] B[i][j]也要更新
求出所有对答案有贡献的 F [ i ] [ j ] F[i][j] F[i][j]后,开始处理队列
按照给出的字典序暴力枚举
S [ i ] S[i] S[i]表示 i i i能对后面贡献多少个逆序对
初始化 S [ i ] = i − 1 S[i]=i-1 S[i]=i1
若当前处理到第 i i i个位置
那么有式子 F [ i − 1 ] [ K − s [ g [ i ] [ j ] ] ] F[i-1][K-s[g[i][j]]] F[i1][Ks[g[i][j]]](注意,这里的 i i i是倒着来的,读入时也要倒着读入)
此时, F [ i − 1 ] [ K − F [ i − 1 ] [ K − s [ g [ i ] [ j ] ] ] ] F[i-1][K-F[i-1][K-s[g[i][j]]]] F[i1][KF[i1][Ks[g[i][j]]]] P P P就有两种情况
1: F [ i − 1 ] [ K − s [ g [ i ] [ j ] ] ] ≥ P F[i-1][K-s[g[i][j]]]≥P F[i1][Ks[g[i][j]]]P
2: F [ i − 1 ] [ K − s [ g [ i ] [ j ] ] ] < P F[i-1][K-s[g[i][j]]]<P F[i1][Ks[g[i][j]]]P
情况1:这说明当前这个位置 i i i是正确的,那么输出,更新 K = K − s [ g [ i ] [ j ] ] K=K-s[g[i][j]] K=Ks[g[i][j]],更新 S [ g [ i ] [ j ] + 1 − > n ] S[g[i][j]+1->n] S[g[i][j]+1>n],进入下个数的选择
情况2:这说明 i i i还是太小,继续枚举下一个数,更新 P = P − F [ i − 1 ] [ K − s [ g [ i ] [ j ] ] ] P=P-F[i-1][K-s[g[i][j]]] P=PF[i1][Ks[g[i][j]]]
附加说明:若当前这个数选完 N N N个后都未出现情况1,那么输出“-1”,即总方案数小于 P P P
结合代码理解

Code

#include<cstdio>
using namespace std;
int n,m,p,i,j,k,num,a[1005][1005],f[1005][10005],s[1005];
bool bz,b[1005][10005],bj[1005];
int main()
{
	freopen("ocd.in","r",stdin);
	freopen("ocd.out","w",stdout);
	scanf("%d%d%d",&n,&m,&p);
	for (i=n;i>=1;i--)
		for (j=1;j<=n;j++)
			scanf("%d",&a[i][j]);
	f[0][0]=1;
	for (i=1;i<n;i++)
	{
		for (j=0;j<=m;j++)
		{
			if (b[i][j]==true) continue;
			for (k=j;k>=j-i+1;k--)
			{
				if (b[i-1][k]==true)
				{
					b[i][j]=true;
					break;
				}
				f[i][j]+=f[i-1][k];
				if (f[i][j]>=p)
				{
					b[i][j]=true;
					break;
				}
			}
		}
	}
	for (i=1;i<=n;i++)
		s[i]=i-1;
	bz=false;
	for (i=n;i>=1;i--)
	{
		for (j=1;j<=n;j++)
		{
			if (bj[a[i][j]]==false) 
			{
				if (f[i-1][m-s[a[i][j]]]>=p||b[i-1][m-s[a[i][j]]])
				{
					bz=true;
					bj[a[i][j]]=true;
					m-=s[a[i][j]];
					for (k=a[i][j]+1;k<=n;k++)
						s[k]--;
					printf("%d ",a[i][j]);
					break;
				}
				p-=f[i-1][m-s[a[i][j]]];
			}
		}
		if (bz==false)
		{
			printf("-1\n");
			break;
		}
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在信号处理领域,DOA(Direction of Arrival)估计是一项关键技术,主要用于确定多个信号源到达接收阵列的方向。本文将详细探讨三种ESPRIT(Estimation of Signal Parameters via Rotational Invariance Techniques)算法在DOA估计中的实现,以及它们在MATLAB环境中的具体应用。 ESPRIT算法是由Paul Kailath等人于1986年提出的,其核心思想是利用阵列数据的旋转不变性来估计信号源的角度。这种算法相比传统的 MUSIC(Multiple Signal Classification)算法具有较低的计算复杂度,且无需进行特征值分解,因此在实际应用中颇具优势。 1. 普通ESPRIT算法 普通ESPRIT算法分为两个主要步骤:构造等效旋转不变系统和估计角度。通过空间平移(如延时)构建两个子阵列,使得它们之间的关系具有旋转不变性。然后,通过对子阵列数据进行最小二乘拟合,可以得到信号源的角频率估计,进一步转换为DOA估计。 2. 常规ESPRIT算法实现 在描述中提到的`common_esprit_method1.m`和`common_esprit_method2.m`是两种不同的普通ESPRIT算法实现。它们可能在实现细节上略有差异,比如选择子阵列的方式、参数估计的策略等。MATLAB代码通常会包含预处理步骤(如数据归一化)、子阵列构造、旋转不变性矩阵的建立、最小二乘估计等部分。通过运行这两个文件,可以比较它们在估计精度和计算效率上的异同。 3. TLS_ESPRIT算法 TLS(Total Least Squares)ESPRIT是对普通ESPRIT的优化,它考虑了数据噪声的影响,提高了估计的稳健性。在TLS_ESPRIT算法中,不假设数据噪声是高斯白噪声,而是采用总最小二乘准则来拟合数据。这使得算法在噪声环境下表现更优。`TLS_esprit.m`文件应该包含了TLS_ESPRIT算法的完整实现,包括TLS估计的步骤和旋转不变性矩阵的改进处理。 在实际应用中,选择合适的ESPRIT变体取决于系统条件,例如噪声水平、信号质量以及计算资源。通过MATLAB实现,研究者和工程师可以方便地比较不同算法的效果,并根据需要进行调整和优化。同时,这些代码也为教学和学习DOA估计提供了一个直观的平台,有助于深入理解ESPRIT算法的工作原理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值