Description
X X X X X
X X X
X X X
X
In addition, Mr. Young wants the students in each row arranged so that heights decrease from left to right. Also, student heights should decrease from the back to the front. Thinking about it, Mr. Young sees that for the 12-student example, there are at least two ways to arrange the students (with 1 as the tallest etc.):
1 2 3 4 5 1 5 8 11 12
6 7 8 2 6 9
9 10 11 3 7 10
12 4
Mr. Young wonders how many different arrangements of the students there might be for a given arrangement of rows. He tries counting by hand starting with rows of 3, 2 and 1 and counts 16 arrangements:
123 123 124 124 125 125 126 126 134 134 135 135 136 136 145 146
45 46 35 36 34 36 34 35 25 26 24 26 24 25 26 25
6 5 6 5 6 4 5 4 6 5 6 4 5 4 3 3
Mr. Young sees that counting by hand is not going to be very effective for any reasonable number of students so he asks you to help out by writing a computer program to determine the number of different arrangements of students for a given set of rows.
Input
Output
Sample Input
1
30
5
1 1 1 1 1
3
3 2 1
4
5 3 3 1
5
6 5 4 3 2
2
15 15
0
Sample Output
1
1
16
4158
141892608
9694845
Solution:
本題是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; }