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

xiaoxiao2021-02-27  107

题目链接: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是双倍经验题(手动滑稽)

转载请注明原文地址: https://www.6miu.com/read-16087.html

最新回复(0)