首页 > 其他分享 >51nod 1370 排列与操作

51nod 1370 排列与操作

时间:2023-04-04 12:02:16浏览次数:49  
标签:排列 示例 51nod 元素 1370 序列 操作



1370 排列与操作



题目来源:  TopCoder


基准时间限制:2 秒 空间限制:131072 KB 分值: 320  难度:7级算法题



 收藏

 关注

给定N长排列P,其中排列指数集{1,2,3...N}组成的一个序列,序列中每个元素恰好出现一次。初始时这个排列是给出的。之后你可以进行不超过K次操作(也就是说你可以操作0次,1次..K次),每次操作如下:
1)选择一个连续的非空的子区间[L,R],其对应元素为{P[L],P[L+1],..,P[R]};
2)设这个区间元素最大值为MAX,测将这个区间的所有元素都重新赋值为MAX。
问在K次以内的操作中,你一共能构造出多少种不同的序列出来,输出这个结果 modulo1,000,000,007后的结果。

注意:两个序列A,B不同是指存在元素位置下标 i,满足A[i]!=B[i].
提示:样例中第2个小数据可以构造的4组结果包括:(3, 1, 2),(3, 2, 2),(3, 3, 2),(3, 3, 3).


Input


多组测试数据,第一行一个整数T,表示测试数据数量,1<=T<=3。每组测试数据有相同的结构构成。每组数据的第一行包含两个整数N,K,其中1<=N<=200,0<=K<=200。接下来N行每行一个整数Pi,表示排列P中第i个元素,保证1~N各出现一次。


Output


每组数据一行输出,即能构造的不同序列个数mod 10^9+7后的结果。


Input示例


32 112 3 2 3 1 2 4 2 4 3 2 1


Output示例


2413



孔炤  (题目提供者)


C++的运行时限为:2000 ms ,空间限制为:131072 KB  示例及语言说明请按这里





【分析】

DP

dp[i][j][k]表示前i个数字,当前序列位置为j,共操作k次得到的序列方案数

需要前缀和优化



【代码】

//51nod1370 排列与操作 
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int mod=1e9+7;
const int mxn=205;
int T,n,m;
int dp[mxn][mxn][mxn];
int p[mxn],pre[mxn],nxt[mxn],s[mxn][mxn];
inline int solve()
{
	int i,j,k,x;
	scanf("%d%d",&n,&m);
	memset(dp,0,sizeof dp);
	fo(i,1,n) scanf("%d",&p[i]);
	dp[0][0][0]=1;
	p[0]=p[n+1]=n+1;
	fo(i,1,n)
	{
		j=i;while(p[j-1]<p[i]) j--;pre[i]=j;
		j=i;while(p[j+1]<p[i]) j++;nxt[i]=j;
	}
	fo(i,1,n)
	{
		memset(s,0,sizeof s);
		fo(k,0,min(i,m)) fo(j,0,nxt[i])
		  s[k][j+1]=(s[k][j]+dp[i-1][j][k])%mod;
		fo(j,pre[i],nxt[i])
		{
		    fo(k,1,min(i,m))
		    {
		  	    if(j!=i)
		  	  	  dp[i][j][k]=(dp[i][j][k]+s[k-1][j]-s[k-1][pre[i]-1])%mod;
			    else
				  dp[i][j][k]=(dp[i][j][k]+s[k-1][j-1]-s[k-1][pre[i]-1])%mod;
//		  	  if(j!=i) fo(x,pre[i]-1,j-1)
//				dp[i][j][k]=(dp[i][j][k]+dp[i-1][x][k-1])%mod;
//		  	  else fo(x,pre[i]-1,j-2)
//		  	    dp[i][j][k]=(dp[i][j][k]+dp[i-1][x][k-1])%mod;
		    }
		}
		fo(k,0,min(i,m))
		  dp[i][i][k]=(dp[i][i][k]+dp[i-1][i-1][k])%mod;
		fo(j,0,n) fo(k,0,min(i-1,m))
		  dp[i][j][k]=(dp[i][j][k]+dp[i-1][j][k])%mod;
	}
	int ans=0;
	fo(i,0,m) ans=(ans+dp[n][n][i])%mod;
	return (ans+mod)%mod;
}
int main()
{
	int i,j;
	scanf("%d",&T);
	while(T--)
	  printf("%d\n",solve());
	return 0;
}
/*
1
2 1
1 2
*/



标签:排列,示例,51nod,元素,1370,序列,操作
From: https://blog.51cto.com/u_15967757/6168373

相关文章

  • 51nod 1486 大大走格子
    1486 大大走格子题目来源: CodeForces基准时间限制:1 秒空间限制:131072 KB分值: 160 难度:6级算法题 收藏 关注有一个h行w列的棋盘,里面有一些格子是不能走的,现在要求从左上角走到右下角的方案数。Input单组测试数据......
  • 51nod 1149 Pi的递推式
    1149 Pi的递推式基准时间限制:1 秒空间限制:131072 KB分值: 640 难度:8级算法题 收藏 关注F(x)=1(0<=x<4)F(x)=F(x-1)+F(x-pi)(4<=x)Pi=3.1415926535.....现在给出一个N,求F(N)。由于结果巨......
  • 【专题】排列逆序数的奇偶性
    排列逆序数的奇偶性是一个十分常见的属性。不同于直接求逆序数,由于排列的性质,这玩意是可以\(\mathcalO(n)\)直接求解的。为了完成这一点,引入如下基本结论:排列两元素对换,逆序数奇偶性改变。排列的逆序数同余\(n-\#\)环。第一点,在大多数线性代数教材中都有所提及。第二......
  • 【LEETCODE】​​1053. 交换一次的先前排列​
    1053.交换一次的先前排列难度中等95给你一个正整数数组 arr(可能存在重复的元素),请你返回可在 一次交换(交换两数字 arr[i] 和 arr[j] 的位置)后得到的、按字典序排列小于 arr 的最大排列。如果无法这么操作,就请返回原数组。 示例1:输入:arr=[3,2,1]输出:[3,1,2]解释:交换2......
  • 力扣-441. 排列硬币
    你总共有 n 枚硬币,并计划将它们按阶梯状排列。对于一个由k行组成的阶梯,其第i行必须正好有i枚硬币。阶梯的最后一行可能是不完整的。给你一个数字 n,计算并返回可形成完整阶梯行的总行数。应该首先判断数据源是否是有序的,先二分。varrs=ArrangeCoins(180428938......
  • 校周赛-我左看右看上看下看 原来每个排列都不简单
    题目描述ABCDEFGBABCDEFCBABCDEDCBABCDEDCBABC这是一个5行7列的图形,请找出这个图形的规律,并输出一个n行m列的图形。输入格式输入一行,包含两个整数n和m,分别表示你要输出的图形的行数的列数。输出格式输出n行,每个m个字符,为你的图形。样例......
  • 递归实现排列型枚举
    #include<iostream>usingnamespacestd;constintN=10;intn;intstate[N];boolused[N];voiddfs(intu){if(u==n+1){for(inti=1;i<=n;i++){cout<<state[i]<<"";}cout<<end......
  • 567. 字符串的排列
    力扣题目链接给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,返回 false 。换句话说,s1 的排列之一是 s2 的 子串 。示例1:输入:s1="ab"s2="eidbaooo"输出:true解释:s2包含s1的排列之一("ba").示例2:输入:s......
  • day29 打卡491.递增子序列 46.全排列 47.全排列 II
    day29打卡491.递增子序列46.全排列47.全排列II491.递增子序列491题目链接classSolution{List<List<Integer>>result=newArrayList<>();LinkedList<......
  • 代码随想录day 28 491. 递增子序列 | * 46.全排列 | 47.全排列 II
    给定一个整型数组,你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2。示例:输入:[4,6,7,7]输出:[[4,6],[4,7],[4,6,7],[4,6,7,7],[6,7......