NC21617. 楼房
描述
给你n个数1 2 3。。n,代表n个楼,第i个楼的高度为i,每个楼会有一种颜色
现在问有多少的排列满足从左往右(站在左边很远的地方看)看能看到L种颜色(即看到了L-1次颜色的变化),答案对1e9+9取模
如果两个相同颜色楼的高度分别为H1,H2 (H1 < H2), H1在左边,且H1 H2之间的楼都比H1矮,那么站在左边来看就是一种颜色
你能看到一个楼的前提是这个楼之前的楼都比它矮
输入描述
第一行输入两个整数n,L(1 ≤ n ≤ 1296) , (1 ≤ L ≤ n)
第二行输入 n个整数ci表示每个楼的颜色 (1 ≤ ci ≤ n)
输出描述
输出一个整数
示例1
输入:
4 3 1 1 2 1
输出:
6
说明:
1, 2, 3, 4 (1,2同色,看上去就是一种颜色,因此这个排列只能看到3种颜色)示例2
输入:
8 5 1 2 2 3 3 3 1 4
输出:
432
C++11(clang++ 3.9) 解法, 执行用时: 121ms, 内存消耗: 20116K, 提交时间: 2019-12-11 22:33:45
#include<bits/stdc++.h> #define ll long long using namespace std; ll ans,n,m,p=1e9+9,jc[2010],ny[2010],a[2010],b[1301][1301],g[1301][1301],f[1301]; ll ksm(ll x,ll y){ ll xlh=1; while(y){ if(y&1)xlh=xlh*x%p; x=x*x%p; y/=2; } return xlh; } int main(){ ll i,j; scanf("%lld%lld",&n,&m); jc[0]=ny[0]=1; for(i=1;i<=n;i++)jc[i]=jc[i-1]*i%p,ny[i]=ksm(jc[i],p-2); for(i=1;i<=n;i++)scanf("%lld",&a[i]); for(i=1;i<=n/2;i++)swap(a[i],a[n-i+1]); g[a[1]][1]=1;f[1]=1;b[1][1]=1; ans=(ans+b[1][m]*jc[n-1])%p; for(i=2;i<=n;i++){ for(j=1;j<i;j++){ b[i][j+1]=(b[i][j+1]+f[j]*jc[i-2]%p)%p; b[i][j+1]=(b[i][j+1]-g[a[i]][j]*jc[i-2]%p+p+g[a[i]][j+1]*jc[i-2]%p)%p; } b[i][1]=g[a[i]][1]*jc[i-2]%p; for(j=1;j<=i;j++)f[j]=(f[j]+b[i][j]*ny[i-1]%p)%p,g[a[i]][j]=(g[a[i]][j]+b[i][j]*ny[i-1]%p)%p; ans=(ans+b[i][m]*jc[n-1]%p*ny[i-1])%p; //printf("%lld\n",ans); } printf("%lld",ans); }