排列问题 permutation(似乎原题是SRM 592 Little Elephant And Permutation Div1?)

来源:互联网 发布:数据分析理论与方法 编辑:程序博客网 时间:2024/06/03 21:31

排列问题 permutation

题目描述

长度为N的排列是一个序列(a1,a2,...,an),恰好包含从1到N的每一个数字。例如,(3,1,4,5,2)是一个长度为5的排列。

对于两个排列a和b,定义

magic(a,b)=max(a1,b1)+max(a2,b2)+...+max(an,bn)

给定整数N和K,求有多少对排列a和b 满足a和b的长度都为N,并且magic(a,b)K

输入格式

第1行:2个整数N和K

输出格式

第1行:1个整数,表示答案,答案模1,000,000,007

输入样例

2 4

输出格式

2

样例说明

2个长度为2的排列一共有4种情况:
* magic( (1,2), (1,2) ) = 1+2 = 3
* magic( (1,2), (2,1) ) = 2+2 = 4
* magic( (2,1), (1,2) ) = 2+2 = 4
* magic( (2,1), (2,1) ) = 2+1 = 3
magic值大于等于4的有2对排列。

数据范围

50%的数据
* N20

100%的数据
* N50
* K2500

限制

  • 时间: 1 S
  • 空间: 128M

我这个措起辞来狗屁不通毫无逻辑的人竟然会写一篇我自己都是看着题解才勉强过掉老师出的随机数据的题....

先附一段官方题解:

本来打算把老师给的pdf的内容粘上去结果发现似乎很难然后又懒得开lantern懒得翻译所以就凑合看吧..

A good idea is then to guarantee that we decide the positions for the numbers in an order. The
best order is decreasing instead of increasing. If in the example above, x is guaranteed to be
smaller than a , b and c, then it is easy to see that whenever x is made to share row with another
number, the magic will not change. Instead, if x is put in rows that were previously empty, the
score will increase by x for each row of that kind that is picked.

n: There are n numbers for which we didn’t decide a position yet. This means that the next number is n.
k: The requirement. The remaining decisions need to increase the magic number by at least k.
s: The number of empty columns.
o_a: The number of cells in the top that have the respective bottom cell filled. The number of
occupied cells in the top.
o_b: The number of occupied cells in the bottom.

Dynamic programming
The recurrence relation is acyclic because n always decreases. We can use dynamic programming
so that each combination of parameters is evaluated exactly once. There will be a couple of issues
though. (N <= 50), (K <= 2500) and there appear to be O(KN^4 ) combinations of
parameters. This complexity is great for the time limit but not so good for the memory limit. We
need more work.

Occupied cells
Notice that in all steps in the recurrence (o_a = o_b). Whenever o_a is increased so is o_b
and they also decrease in the same way. So we can just replace them o_a and o_b by a
single value o.
f(n,k,s,o)=s*f(n-1,max(0,k-n),s-1,o)+s*(s-1)*f(n-1,max(0,k-2n),s-2,o+1)+o^2*f(n-1,k,s,o-1)+2*o*s*f(n-1,max(0,k-n),s-1,o)
This cuts the estimated complexity to O(K N^3)

然而我并!没!有!用这种方法去写…2333
先占个坑吧..说不定以后什么时候就填上了呢QWQ

然后再介绍一种题解(当时我对着这个题解推了半天)

我们发现可以先固定排列a为(1,2,…,n),最后将答案乘以n!即可。
我们可以设计状态f[i][j][k]表示已经在b中填充了数1到i,填在下标为i+1到n的数有j个,满足max(a[p],b[p])<=i的max(a[p],b[p])的和为k,这样的的填充方法数。
于是可以分类:
1.将数i填在下标为i处,则k+=i,j不变.
2.将数i填在下标小于i处,下标为i处填入了小于i的数,则k+=2 * i, j–.
3.将数i填在下标小于i处,下标为i处填入了大于i的数,则k+=i,j不变.
4.将数i填在下标大于i处,下标为i处填入了大于i的数,则k不变,j++.
5.将数i填在下标大于i处,下标为i处填入了小于i的数,则k+=i,j不变.
最终答案为f[n][0][x]的和,其中x>=k.

然后下为我几乎看着(老师给的)标程想了半天后才过掉老师出的随机数据的代码..

#include<cstdio>#define mod 1000000007#define min(a,b) (a)<(b)?(a):(b)int n,m,ans,f[55][55][2505];long long c;int main(){    freopen("permutation.in","r",stdin);    freopen("permutation.out","w",stdout);    int i,j,k;    scanf("%d%d",&n,&m);    f[0][0][0]=1;    for(i=1;i<=n;i++)        for(j=0;j<=i;j++)            for(k=0;k<=m;k++)            {                c=f[i-1][j][k];                f[i][j][min(k+i,m)]=(f[i][j][min(k+i,m)]+((2*j+1)*c)%mod)%mod;//1,3,5                f[i][j+1][k]=(f[i][j+1][k]+c)%mod;//4                if(j) f[i][j-1][min(m,k+i*2)]=(f[i][j-1][min(m,k+i*2)]+(c*j*j)%mod)%mod;//2            }    c=f[n][0][m];    for(i=1;i<=n;i++) c=(c*i)%mod;    ans=c;    printf("%d\n",ans);}

接着详细介绍(其实详细不到哪去…..?)
根据上文,1,3,5其实是可以合并的..
然后,再加上各自的方案数..
具体的推导过程我也不是特别清楚所以先占个坑等完全想清楚再填…

原创粉丝点击