PA2021 Od deski do deski 题解
Solution
比较懒,所以放了一个OJ里的链接。
这个题感觉还是比较可做。考虑如何判断一个是否合法,那么我们可以使用 dp,转移式即为:
\[dp_i=Or_{j=1}^{i-1}[a_i=a_j]dp_{j-1}
\]
那么,我们可以对此进行 dp,我们设 \(f_{i,j,0/1}\) 表示前面 \(i\) 个,\(dp_{k-1}=1\) 的 \(a_k\) 构成的集合大小为 \(j\),\(dp_i=0/1\) 的方案数,我们不难得出转移式:
\[f_{i,j,1}=j\times (f_{i-1,j,0}+f_{i-1,j,1})
\]
\[f_{i,j,0}=(m-j+1)\times f_{i-1,j-1,1}+(m-j)\times f_{i-1,j,0}
\]
复杂度 \(\Theta(n^2)\)。
Code
#include <bits/stdc++.h>
using namespace std;
#define Int register int
#define mod 1000000007
#define MAXN 3005
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}
int n,m,f[MAXN][MAXN][2];
int mul (int a,int b){return 1ll * a * b % mod;}
int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;}
void Add (int &a,int b){a = add (a,b);}
void Sub (int &a,int b){a = dec (a,b);}
signed main(){
read (n,m),f[1][1][0] = m;
for (Int i = 2;i <= n;++ i)
for (Int j = 1;j <= i;++ j){
f[i][j][1] = mul (j,add (f[i - 1][j][0],f[i - 1][j][1]));
f[i][j][0] = add (mul (m - (j - 1),f[i - 1][j - 1][1]),mul (m - j,f[i - 1][j][0]));
}
int ans = 0;
for (Int i = 1;i <= n;++ i) Add (ans,f[n][i][1]);
write (ans),putchar ('\n');
return 0;
}