标签:排列 部落 int ....... SDOI2010 相邻 ......... dp
题目
求1~n的全排列数目,使得对于\(i\geq 3\),\(a_{i},a_{i-1}\)的大小关系与\(a_{i-1},a_{i-2}\)的大小关系不同
思路
题目还有另外一种格式:求一种全排列,使得这个排列要么满足奇数项的高度比相邻位置都大, 要么满足偶数项的高度比相邻位置都大.
设\(dp_{i,j}\)表示用了前\(i\)个数字,\(a_1 = j\)且\(a_1 > a_2\)时的方案数;
有一个神奇的性质:\(j-1\)和\(j\)不相邻时,交换两数可以形成一种新的方案(比较显然),所以由\(dp_{i,j-1}\)可以转移到\(dp_{i,j}\),即对于当前任意一个排列\(j.......j-1.......\),都有之前的一个排列\(j-1.........j.......\)与之对应
如果\(j-1\)和\(j\)相邻,对于当前任意一个排列\(j,j-1.........\),都可以用之前的一个排列\(j-1..........\)前面加个\(j\)得到(且此时\(j-1\)比后面的数小),即求\(i-1\)个数的排列数,由于这种排列不符合定义(\(a_1>a_2\)),需要做个变换:将每个数\(x\)变成\(i-x\),如序列1,2,4,3变成4,3,1,2,\(j-1\)变成了\(i-j+1\),即\(dp_{i-1,i-j+1}\)可以转移到\(dp_{i,j}\)
\(dp_{i,j} = dp_{i,j-1} + dp_{i-1,i-j+1}\),需要滚动数组优化
#include<bits/stdc++.h>
#define N 5005
using namespace std;
typedef long long ll;
int n,mod;
ll f[2][N];
int main()
{
cin>>n>>mod;
int las=0,now=1;
f[now][2]=1;//两个数只有2,1排法
for(int i=3;i<=n;++i)//用i个数
{
swap(las,now);
for(int j=1;j<=i;++j)
{
f[now][j]=(f[now][j-1]+f[las][i-j+1])%mod;
}
}
ll ans=0;
for(int i=1;i<=n;++i) ans=(ans+f[now][i])%mod;
cout<<ans*2%mod;
return 0;
}
标签:排列,部落,int,.......,SDOI2010,相邻,.........,dp 来源: https://www.cnblogs.com/Chtholly/p/11755482.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。