LOJ #3600. 「PA 2021」Od deski do deski
阿新 • • 發佈:2022-04-21
題面傳送門
看到題解直呼芥末醬。
首先考慮給定一個序列如何判定合法,容易發現可以dp:設\(dp_i\)為到了\(i\)這個點能不能刪空,那麼顯然\(dp_{i}=dp_{j-1}\or [a_i==a_j]\)
發現\(a_i\)如果可行那麼只能從所有\(dp_{j-1}=1\)的\(a_j\)中取值,這啟示我們可以將上一維的dp狀態和已經有的顏色數壓進狀態裡。
設\(f_{i,j,0/1}\)表示\([1,i]\)這個字首,顏色有\(j\)種,前一個dp狀態是\(0/1\)的方案數,轉移平凡。
時間複雜度\(O(n^2)\)
code:
#include<bits/stdc++.h> #define I inline #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define abs(x) ((x)>0?(x):-(x)) #define ll long long #define db double #define lb long db #define N (3000+5) #define M (7000+5) #define K (1000+5) #define mod 1000000007 #define Mod (mod-1) #define eps (1e-9) #define ull unsigned ll #define it iterator #define Gc() getchar() #define Me(x,y) memset(x,y,sizeof(x)) #define Mc(x,y) memcpy(x,y,sizeof(x)) #define d(x,y) (n*(x-1)+(y)) #define R(n) (rand()*rand()%(n)+1) #define Pc(x) putchar(x) #define LB lower_bound #define UB upper_bound #define PB push_back using namespace std; int n,m,k;ll Ans,dp[N][N][2]; int main(){ freopen("1.in","r",stdin); int i,j,x,y;scanf("%d%d",&n,&m);dp[0][0][1]=1;for(i=1;i<=n;i++){ for(j=0;j<=min(i,m);j++){ dp[i][j][0]=dp[i-1][j][0]*(m-j)%mod;j&&(dp[i][j][0]=(dp[i][j][0]+dp[i-1][j-1][1]*(m-j+1))%mod); dp[i][j][1]=(dp[i-1][j][0]+dp[i-1][j][1])*j%mod; } }for(i=0;i<=min(n,m);i++) Ans+=dp[n][i][1];printf("%lld\n",Ans%mod); }