1. 程式人生 > >BZOJ[1925] [Sdoi2010]地精部落

BZOJ[1925] [Sdoi2010]地精部落

hide set ans 一個數 play () ont open lose

很難理解的一個DP

首先先說明兩個狀態數組,f[i][j]表示當前序列的長度為i,最後一位是第j小,且第i位為山谷的方案數,同理g[i][j]表示f[i][j]表示當前序列的長度為i,最後一位是第j小,且第i位為山峰的方案數;

那麽f就是能從g轉移過來,

那麽f[i][j]就等於g[i-1][k] (j<=k<=i-1);然後考慮優化,可以想象把整段山脈倒過來,那麽f[i][j]與g[i][i-j+1]的方案書是一樣的,那麽f[i][j]就等於f[i-1][k](1<=k<=i-j);

然後我一直不理解的是,這裏的j只是表示一個相對的大小關系,當他聯系到具體的數字的時候,不用考慮第j小的數字到底要選哪個麽? 是不是要乘一個 j... 什麽的東西,

其實這個相對關系可以說是唯一的,他只是表示滿足當前大小關系的狀態的方案數,而不是滿足這種關系具體有多少可能,當轉移到最後的n的時候,第j小時哪一個數字就是確定的,然後從之前轉移過來的每一種狀態也都就是確定的,也就是之前說的唯一的;

技術分享
 1 #include <cmath>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <iostream>
 6 #include <algorithm>
 7 using namespace
std; 8 typedef long long LL; 9 int n; 10 LL mod; 11 LL f[3][4300]; 12 int main(){ 13 // freopen("a.in","r",stdin); 14 scanf("%d%lld",&n,&mod); 15 f[1][1]=1; int rol=0; 16 for(int i=2;i<=n;i++){ 17 memset(f[rol],0,sizeof(f[rol])); 18 LL sum=0; 19 for(int j=i-1
;j>=1;j--){ 20 sum=(sum+f[rol^1][i-j])%mod; 21 // cout<<"sim== "<<sum<<endl; 22 f[rol][j]=sum; 23 } 24 rol^=1; 25 } 26 LL ans=0; 27 for(int i=1;i<=n;i++){ 28 ans=(ans+f[rol^1][i])%mod; 29 } 30 ans=(ans*2)%mod; 31 cout<<ans<<endl; 32 }
View Code

BZOJ[1925] [Sdoi2010]地精部落