SP3734 PERIODNI - Periodni
题解:
第一道笛卡尔树dp
会发现以一个点为分界 如果左边大于它右边大于它 那么大于的那部分是相互不影响的
于是我们对序列建立笛卡尔树
满足父亲节点的v<儿子节点的v 然后这棵树的中序遍历为原序列
这样子我们就可以dp了
考虑一个矩形的方案数
$C(n,i)*C(m,i)*i!$ 其中$i!$表示行列自由匹配
然后现在的话我们只需要统计当前点包含的行数-用掉的 以及 列
另外处理逆元前缀积有一个比正着递推常数小的方法。。(少了取模和除法运算)
代码:
#include <bits/stdc++.h> using namespace std; #define rint register int #define IL inline #define rep(i,h,t) for(int i=h;i<=t;i++) #define dep(i,t,h) for(int i=t;i>=h;i--) #define ll long long #define me(x) memset(x,0,sizeof(x)) namespace IO{ char ss[1<<24],*A=ss,*B=ss; IL char gc() { return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++; } template<class T> void read(T &x) { rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48); while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f; } char sr[1<<24],z[20]; int Z,C1=-1; template<class T>void wer(T x) { if (x<0) sr[++C1]='-',x=-x; while (z[++Z]=x%10+48,x/=10); while (sr[++C1]=z[Z],--Z); } IL void wer1() { sr[++C1]=' '; } IL void wer2() { sr[++C1]='\n'; } template<class T>IL void maxa(T &x,T y) {if (x<y) x=y;} template<class T>IL void mina(T &x,T y) {if (x>y) x=y;} template<class T>IL T MAX(T x,T y){return x>y?x:y;} template<class T>IL T MIN(T x,T y){return x<y?x:y;} }; using namespace IO; const int N=600; const int N1=1e6+100; const int N2=1e6; const int mo=1e9+7; int n,k,v[N],s[N],t,ls[N],rs[N]; int jc[N1],jc2[N1]; int dp[N][N],w[N]; ll tmp[N]; int ksm(int x,int y) { if (y==0) return(1); if (y==1) return(x); int k=ksm(x,y/2); k=1ll*k*k%mo; if (y%2==1) k=1ll*k*x%mo; return k; } int C(int x,int y) { if (x<y) return(0); return 1ll*jc[x]*jc2[y]%mo*jc2[x-y]%mo; } void dfs(int x,int y) { w[x]=1; if (ls[x]) { dfs(ls[x],v[x]); w[x]+=w[ls[x]]; } if (rs[x]) { dfs(rs[x],v[x]); w[x]+=w[rs[x]]; } me(tmp); rep(i,0,w[x]) { ll y=0; rep(j,0,i) y+=1ll*dp[ls[x]][j]*dp[rs[x]][i-j]%mo; tmp[i]=y%mo; } rep(i,0,w[x]) rep(j,0,i) (dp[x][i]+=1ll*tmp[j]*C(v[x]-y,i-j)%mo *C(w[x]-j,i-j)%mo*jc[i-j]%mo)%=mo; } int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); read(n); read(k); int rt; rep(i,1,n) { read(v[i]); bool tt=0; while (v[i]<v[s[t]]) t--,tt=1; rs[s[t]]=i; if (tt) ls[i]=s[t+1]; s[++t]=i; } rt=rs[0]; jc[0]=1; jc2[0]=1; rep(i,1,N2) jc[i]=1ll*jc[i-1]*i%mo; jc2[N2]=ksm(jc[N2],mo-2); dep(i,N2-1,1) jc2[i]=1ll*jc2[i+1]*(i+1)%mo; dp[0][0]=1; dfs(rt,0); cout<<dp[rt][k]<<endl; return 0; }