zoukankan      html  css  js  c++  java
  • [SDOI2010]地精部落

    题目

    求1~n的全排列数目,使得对于(igeq 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;
    }
    
  • 相关阅读:
    POJ_1485_dp
    POJ_1376_bfs
    [noi1994]海盗
    [noi1755]Trie
    [luogu3733]八纵八横
    [noi1774]array
    [noi1773]function
    [noi1754]SA
    [noi1779]D
    [bzoj4873]寿司餐厅
  • 原文地址:https://www.cnblogs.com/Chtholly/p/11755482.html
Copyright © 2011-2022 走看看