POJ 2279 杨氏矩阵与钩子公式

本题是lyd神犇的进阶指南上的DP题,状态转移方程看懂了,但是看似简单去实现有点复杂啊,于是取搜罗本题的勾长公式的解法。

 

杨表由有限的方格组成。

 

对于一个正整数,给定一个整数分拆λ(10=1+4+5),则对应一个杨表(注意这是一个递降的过程,也就是说下面一行的方格数要大于等于上一行的方格数)。

 

 技术分享

 

一个(1,4,5)分拆表示的杨表

 

杨表与整数分拆λ一一对应。

 

给定一个杨表,一共有n个方格。那么把1到n这n个数字填到这个杨表中,使得每行从左到右都是递增的,每列从下到上也是递增的。如图

 

技术分享 

 

一个杨表的表示

 

【勾长】对于杨表中的一个方格v,其勾长hook(v)等于同行右边的方格数加上同列上面的方格数,再加上1(也就是他自己)。

 

【勾长公式】用表示杨表个数,则

 

 技术分享

 

对于分拆10 = 5 + 4 + 1 的应的杨表. 因此共有

 

技术分享种方法。

 

公式题。求出同行右边的方格数+同列上面的方格数+1。唯一注意的地方是最后除的时候要防止溢出。

 

转载:

 这个题嘛,标准做法是线性DP。

 f[a1,a2,a3,a4,a5]表示每排从左起占了a1,a2,a3,a4,a5个人的方案数,f[0,0,0,0,0]=1。

 转移方程为:当a1<N1,f[a1+1,a2,a3,a4,a5]+=f[a1,a2,a3,a4,a5],其余同理。

 上面是lyd讲的,本蒟蒻觉得有点错,但说不清哪儿有问题(也可能本身没问题),路过的dalao帮看一看,谢告知。

 那么简单做法就是:先去了解一下杨氏矩形和勾长公式,然后直接用公式做。我这种蒟蒻就选了这种方法……

杨氏矩阵定义(需满足的条件/特征):

(1)若格子(i,j),则该格子的右边和上边一定没有元素;

(2)若格子(i,j)有元素data[i][j],则该格子右边和上边相邻的格子要么没有元素,要么有比data[i][j]大的元素。

 显然有同已写元素组成的杨氏矩阵不唯一,1~n组成杨氏矩阵的个数可以写出:

F[1]=1,F[2]=2,F[n]=F[n-1]+(n-1)*F[n-2] (n>2)。

 钩子长度的定义:该格子右边的格子数和它上边的格子数之和;

 钩子公式:对于给定形状,不同的杨氏矩阵的个数为(n!/(每个格子的钩子长度加1的积))。

 知道了这些再做这个题就很方便了……

#include<bits/stdc++.h>
#define ll long long
#define il inline
using namespace std;
ll n,cnt,x,y,tmp,num[40],sum[5200];
il ll gcd(int a,int b){return b?gcd(b,a%b):a;}
int main()
{
    while(scanf("%lld",&n)&&n){
        memset(sum,0,sizeof(sum));
        cnt=0,x=1,y=1;
        for(int i=1;i<=n;i++)scanf("%lld",&num[i]);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=num[i];j++){
                cnt++;
                for(int k=i+1;k<=n;k++){
                    if(num[k]>=j)sum[cnt]++;
                    else break;
                }
                sum[cnt]+=num[i]-j+1;
            }
        for(int i=1;i<=cnt;i++){
            x*=i;y*=sum[i];
            tmp=gcd(x,y);
            x/=tmp;y/=tmp;
        }
        printf("%lld\n",x/y);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值