Live2D

PA2021 Od deski do deski 题解

link

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;
}
posted @ 2022-01-25 14:47  Dark_Romance  阅读(95)  评论(0编辑  收藏  举报