【POJ2279】【杨氏矩阵/钩子公式】Mr. Young's Picture Permutations

题目链接http://poj.org/problem?id=2279
题意:给出一个n行的矩阵,每一行有a[i]个数,总共有sum个数,要求每一个位置的数必须比上面的数和左面的数大,求总方案数
题解
刚开始看到这道题,潜意识里是要爆搜(貌似我也只会这样做了)
毕竟暴力出滑稽
但貌似有DP解法???(听lyd讲了还是不会啊)
只好强势安利一个【杨氏矩阵/钩子公式】

以下部分转自 ACdreamers
杨氏矩阵又叫杨氏图表,它是这样一个矩阵,满足条件:

(1)如果格子(i,j)没有元素,则它右边和上边的相邻格子也一定没有元素。
(2)如果格子(i,j)有元素a[i][j],则它右边和上边的相邻格子要么没有元素,要么有元素且比a[i][j]大。

1 ~ n所组成杨氏矩阵的个数可以通过下面的递推式得到:
这里写图片描述

下面介绍一个公式,那就是著名的钩子公式

对于给定形状,不同的杨氏矩阵的个数为:n!/(每个格子的钩子长度加1的积)。
其中钩子长度定义为该格子右边的格子数和它上边的格子数之和。

证明的话……
只好挖个坑了
路过了大佬如果知道的话麻烦指教一下蒟蒻

回到这道题目
就是把杨氏矩阵转了个圈
直接套用公式就好了
但为了防止中间结果溢出要步步约分

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
int n,num[10],tot;
LL t1,t2,tmp[110],hhh;
LL gcd(LL a,LL b)
{
    return b?gcd(b,a%b):a;
}
int main()
{
    while(scanf("%d",&n)&&n)
    {
        memset(tmp,0,sizeof(tmp));
        t1=1,t2=1,tot=0;
        for(int i=1;i<=n;i++)
            scanf("%d",&num[i]);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=num[i];j++)
            {
                tmp[++tot]+=num[i]-j+1;
                for(int k=i+1;k<=n;k++)             
                    tmp[tot]+=(num[k]>=j);
            }
        for(int i=1;i<=tot;i++)
        {
            t1*=i;t2*=tmp[i];
            hhh=gcd(t1,t2);
            t1/=hhh;t2/=hhh;    
        }
        printf("%lld\n",t1/t2);
    }
    return 0;
}

听说POJ1825是双倍经验题(手动滑稽)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值