1. 程式人生 > >BZOJ 1996 [Hnoi2010]chorus 合唱隊

BZOJ 1996 [Hnoi2010]chorus 合唱隊

題目連結

題解

區間dp,記f[i][j]表示[i,j][i,j]區間,最後一個取ii的方案數,g[i][j]表示[i,j][i,j]區間最後一個取jj的方案數,狀態轉移很顯然。

程式碼

#include <cstdio>

int read()
{
  int x=0,f=1;
  char ch=getchar();
  while((ch<'0')||(ch>'9'))
    {
      if(ch=='-')
        {
          f=-f;
        }
      ch=getchar();
    }
  while
((ch>='0')&&(ch<='9')) { x=x*10+ch-'0'; ch=getchar(); } return x*f; } const int maxn=1000; const int mod=19650827; int n,h[maxn+10],f[maxn+10][maxn+10],g[maxn+10][maxn+10]; int main() { n=read(); for(int i=1; i<=n; ++i) { h[i]=read(); } for(int i=1; i<=
n; ++i) { f[i][i]=1; } for(int len=2; len<=n; ++len) { for(int i=1; i+len-1<=n; ++i) { int j=i+len-1; f[i][j]=(h[i]<h[i+1])*f[i+1][j]+(h[i]<h[j])*g[i+1][j]; if(f[i][j]>=mod) { f[i][j]-=mod; }
g[i][j]=(h[j]>h[j-1])*g[i][j-1]+(h[j]>h[i])*f[i][j-1]; if(g[i][j]>=mod) { g[i][j]-=mod; } } } int ans=f[1][n]+g[1][n]; if(ans>=mod) { ans-=mod; } printf("%d\n",ans); return 0; }