POJ 2279【杨氏矩阵+钩长公式】

题目链接:http://poj.org/problem?id=22793

题意:给出n行,每行有人数限制a[i],并且a[i]>=a[i+1],总人数暂且称为tot=∑a[i],把 1~tot 这些数字填入矩阵,使得矩阵满足每行单调递增,每列单调递增,求满足要求的矩阵数目。

杨氏矩阵又叫杨氏图表,它是这样一个矩阵,满足条件:

(1)如果格子(i,j)没有元素,则它右边和上边的相邻格子也一定没有元素。

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

1 ~ n所组成杨氏矩阵的个数可以通过下面的递推式得到:

如图就是n=3时的杨氏矩阵。

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

题解:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
int m, a[33];
int sum[1005];
ll gcd(ll a, ll b){
    return b ? gcd(b, a%b) : a;
}
int main()
{
    scanf("%d", &m);
    int id = 0;
    for(int i = 1; i <= m; i++){
        scanf("%d", &a[i]);
    }
    for(int i = 1; i <= m; i++){//第i行
        for(int j = 1; j <= a[i]; j++){//第j列
            id++;
            for(int k = i+1; k <= m; k++){//第i行下面的行
                if(a[k] >= j) sum[id]++;//说明第id个元素下面有元素
                else break;
            }
            sum[id] += (a[i] - j + 1);//加上右边的元素个数在加1
        }
    }
    ll a = 1, b = 1, tmp = 1;
    ll ans = 0;
    for(int i = 1; i <= id; i++){
        a *= i;
        b *= sum[i];
        tmp = gcd(a, b);
        if(tmp != 1){
            a /= tmp;
            b /= tmp;
        }
    }
    ans = a/b;
    printf("%lld\n", ans);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值